From 6a78e011b1aa813b4623c89f3a37abe8bb846455 Mon Sep 17 00:00:00 2001 From: Ilhaan Rasheed Date: Tue, 12 Mar 2024 00:32:55 -0700 Subject: [PATCH 01/73] feat: ` avm/res/container-service/managed-cluster` add additional outbound types (#992) ## Description Adding two new outbound types to the existing AKS module. [![avm.res.container-service.managed-cluster](https://github.com/ilhaan/bicep-registry-modules/actions/workflows/avm.res.container-service.managed-cluster.yml/badge.svg?branch=aks-outbound-type-updates)](https://github.com/ilhaan/bicep-registry-modules/actions/workflows/avm.res.container-service.managed-cluster.yml) --------- Co-authored-by: Alexander Sehr --- avm/res/container-service/managed-cluster/README.md | 6 ++++-- avm/res/container-service/managed-cluster/main.bicep | 5 +++-- avm/res/container-service/managed-cluster/main.json | 10 ++++++---- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/avm/res/container-service/managed-cluster/README.md b/avm/res/container-service/managed-cluster/README.md index e821115b32..55d31f23c1 100644 --- a/avm/res/container-service/managed-cluster/README.md +++ b/avm/res/container-service/managed-cluster/README.md @@ -1548,7 +1548,7 @@ module managedCluster 'br/public:avm/res/container-service/managed-cluster: Date: Tue, 12 Mar 2024 03:41:48 -0400 Subject: [PATCH 02/73] fix: Updated MSI Purview output to convention (#1244) ## Description - Updated MSI Purview output to convention ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.purview.account](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.purview.account.yml/badge.svg?branch=users%2Falsehr%2FmsiOutput)](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.purview.account.yml) | --- avm/res/purview/account/main.bicep | 2 +- avm/res/purview/account/main.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/avm/res/purview/account/main.bicep b/avm/res/purview/account/main.bicep index e74a9b4a19..a62c667df3 100644 --- a/avm/res/purview/account/main.bicep +++ b/avm/res/purview/account/main.bicep @@ -384,7 +384,7 @@ output managedStorageAccountId string = account.properties.managedResources.stor output managedEventHubId string = account.properties.managedResources.eventHubNamespace @description('The principal ID of the system assigned identity.') -output systemAssignedMIPrincipalId string = contains(account.identity, 'principalId') ? account.identity.principalId : '' +output systemAssignedMIPrincipalId string = account.?identity.?principalId ?? '' // =============== // // Definitions // diff --git a/avm/res/purview/account/main.json b/avm/res/purview/account/main.json index 51e217f1d8..6c09d3b5cc 100644 --- a/avm/res/purview/account/main.json +++ b/avm/res/purview/account/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "7616867894603792614" + "templateHash": "11885849494373802730" }, "name": "Purview Accounts", "description": "This module deploys a Purview Account.", @@ -4020,7 +4020,7 @@ "metadata": { "description": "The principal ID of the system assigned identity." }, - "value": "[if(contains(reference('account', '2021-07-01', 'full').identity, 'principalId'), reference('account', '2021-07-01', 'full').identity.principalId, '')]" + "value": "[coalesce(tryGet(tryGet(reference('account', '2021-07-01', 'full'), 'identity'), 'principalId'), '')]" } } } \ No newline at end of file From 6ac5dc792b54753db0739d887f1804f13938458c Mon Sep 17 00:00:00 2001 From: Alexander Sehr Date: Tue, 12 Mar 2024 04:36:07 -0400 Subject: [PATCH 03/73] fix: Updated Pester template test file check & added change to key vault to enable republishing (#1236) ## Description - Updated Pester template test file check - Added change to key vault to enable republishing - Fixed incorrect conflict resolution of pe & max tests ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.key-vault.vault](https://github.com/AlexanderSehr/bicep-registry-modules/actions/workflows/avm.res.key-vault.vault.yml/badge.svg?branch=users%2Falsehr%2Fe2eTestCheck&event=workflow_dispatch)](https://github.com/AlexanderSehr/bicep-registry-modules/actions/workflows/avm.res.key-vault.vault.yml) | --------- Co-authored-by: Erika Gressi <56914614+eriqua@users.noreply.github.com> --- avm/res/key-vault/vault/main.bicep | 4 ++-- avm/res/key-vault/vault/main.json | 6 ++--- .../vault/tests/e2e/max/main.test.bicep | 2 ++ .../tests/connectivity.tests.ps1 | 0 .../private-endpoint/tests/resource.tests.ps1 | 24 ------------------- .../compliance/module.tests.ps1 | 7 +++--- 6 files changed, 11 insertions(+), 32 deletions(-) rename avm/res/key-vault/vault/tests/e2e/{private-endpoint => max}/tests/connectivity.tests.ps1 (100%) delete mode 100644 avm/res/key-vault/vault/tests/e2e/private-endpoint/tests/resource.tests.ps1 diff --git a/avm/res/key-vault/vault/main.bicep b/avm/res/key-vault/vault/main.bicep index bae76f0c3f..7193baf425 100644 --- a/avm/res/key-vault/vault/main.bicep +++ b/avm/res/key-vault/vault/main.bicep @@ -209,7 +209,7 @@ module keyVault_secrets 'secret/main.bicep' = [for (secret, index) in secretList name: secret.name value: secret.value keyVaultName: keyVault.name - attributesEnabled: secret.?attributesEnabled ?? true + attributesEnabled: secret.?attributesEnabled attributesExp: secret.?attributesExp attributesNbf: secret.?attributesNbf contentType: secret.?contentType @@ -223,7 +223,7 @@ module keyVault_keys 'key/main.bicep' = [for (key, index) in (keys ?? []): { params: { name: key.name keyVaultName: keyVault.name - attributesEnabled: key.?attributesEnabled ?? true + attributesEnabled: key.?attributesEnabled attributesExp: key.?attributesExp attributesNbf: key.?attributesNbf curveName: key.?curveName ?? 'P-256' diff --git a/avm/res/key-vault/vault/main.json b/avm/res/key-vault/vault/main.json index aeae460874..40adf90666 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.25.53.49325", - "templateHash": "18302928297760675801" + "templateHash": "5604749365634791124" }, "name": "Key Vaults", "description": "This module deploys a Key Vault.", @@ -1126,7 +1126,7 @@ "value": "[parameters('name')]" }, "attributesEnabled": { - "value": "[coalesce(tryGet(variables('secretList')[copyIndex()], 'attributesEnabled'), true())]" + "value": "[tryGet(variables('secretList')[copyIndex()], 'attributesEnabled')]" }, "attributesExp": { "value": "[tryGet(variables('secretList')[copyIndex()], 'attributesExp')]" @@ -1403,7 +1403,7 @@ "value": "[parameters('name')]" }, "attributesEnabled": { - "value": "[coalesce(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'attributesEnabled'), true())]" + "value": "[tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'attributesEnabled')]" }, "attributesExp": { "value": "[tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'attributesExp')]" diff --git a/avm/res/key-vault/vault/tests/e2e/max/main.test.bicep b/avm/res/key-vault/vault/tests/e2e/max/main.test.bicep index 280869b9b8..e6cc12bba1 100644 --- a/avm/res/key-vault/vault/tests/e2e/max/main.test.bicep +++ b/avm/res/key-vault/vault/tests/e2e/max/main.test.bicep @@ -292,3 +292,5 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' diagnosticDependencies ] }] + +output resourceId string = testDeployment[0].outputs.resourceId diff --git a/avm/res/key-vault/vault/tests/e2e/private-endpoint/tests/connectivity.tests.ps1 b/avm/res/key-vault/vault/tests/e2e/max/tests/connectivity.tests.ps1 similarity index 100% rename from avm/res/key-vault/vault/tests/e2e/private-endpoint/tests/connectivity.tests.ps1 rename to avm/res/key-vault/vault/tests/e2e/max/tests/connectivity.tests.ps1 diff --git a/avm/res/key-vault/vault/tests/e2e/private-endpoint/tests/resource.tests.ps1 b/avm/res/key-vault/vault/tests/e2e/private-endpoint/tests/resource.tests.ps1 deleted file mode 100644 index 4c68a6cd00..0000000000 --- a/avm/res/key-vault/vault/tests/e2e/private-endpoint/tests/resource.tests.ps1 +++ /dev/null @@ -1,24 +0,0 @@ -###################################### -## Additional post-deployment tests ## -###################################### -## -## You can add any custom post-deployment validation tests you want here, or add them spread accross multiple test files in the test case folder. -## -########################### - -param ( - [Parameter(Mandatory = $false)] - [hashtable] $TestInputData = @{} -) - -Describe 'Validate Key Vault' { - - It 'Public endpoint should be disabled' { - - $keyVaultResourceId = $TestInputData.DeploymentOutputs.resourceId.Value - - $deployedResource = Get-AzResource -ResourceId $keyVaultResourceId - - $deployedResource.Properties.publicNetworkAccess | Should -Be 'Disabled' - } -} \ No newline at end of file diff --git a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 index 5ca94a1b60..108904bed5 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 @@ -214,8 +214,9 @@ Describe 'File/folder tests' -Tag 'Modules' { $e2eTestFolderPathList = Get-ChildItem -Directory (Join-Path -Path $moduleFolderPath 'tests' 'e2e') foreach ($e2eTestFolderPath in $e2eTestFolderPathList) { - $pathExisting = Test-Path (Join-Path -Path $e2eTestFolderPath 'main.test.bicep') - $pathExisting | Should -Be $true + $filePath = Join-Path -Path $e2eTestFolderPath 'main.test.bicep' + $pathExisting = Test-Path $filePath + $pathExisting | Should -Be $true -Because "path [$filePath] is expected to exist." } } } @@ -348,7 +349,7 @@ Describe 'Module tests' -Tag 'Module' { } } - It '[] Compiled ARM template should be latest.' -TestCases $armTemplateTestCases { + It '[] The [main.json] ARM template should be based on the current [main.bicep] Bicep template.' -TestCases $armTemplateTestCases { param( [string] $moduleFolderName, From 0f9eba44ac1c105bf64901b633099f7a9cb75eaf Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Tue, 12 Mar 2024 09:44:50 +0000 Subject: [PATCH 04/73] fix: Update Web App Server Farm Module (#1251) ## Description | Pipeline | | -------- | | [![avm.res.web.serverfarm](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.web.serverfarm.yml/badge.svg?branch=jtracey93-patch-1)](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.web.serverfarm.yml) | ![image](https://github.com/Azure/bicep-registry-modules/assets/41163455/6ba46c12-2eb9-44bb-9cdb-c2de96189e26) ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [x] Azure Verified Module updates: - [x] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [x] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [ ] I have run `Set-AVMModule` locally to generate the supporting module files. - [ ] My corresponding pipelines / checks run clean and green without any errors or warnings --- avm/res/web/serverfarm/main.bicep | 2 +- avm/res/web/serverfarm/main.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/avm/res/web/serverfarm/main.bicep b/avm/res/web/serverfarm/main.bicep index 64e1cfa263..89ca6b812f 100644 --- a/avm/res/web/serverfarm/main.bicep +++ b/avm/res/web/serverfarm/main.bicep @@ -83,7 +83,7 @@ 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 (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') 'Web Plan Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b') 'Website Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772') diff --git a/avm/res/web/serverfarm/main.json b/avm/res/web/serverfarm/main.json index a44193aa35..6ccd7bb609 100644 --- a/avm/res/web/serverfarm/main.json +++ b/avm/res/web/serverfarm/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "1573932068035500098" + "templateHash": "14257048735375797880" }, "name": "App Service Plan", "description": "This module deploys an App Service Plan.", @@ -328,7 +328,7 @@ "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 (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')]", "Web Plan Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b')]", "Website Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772')]" From 524a1b855e6e5f4002284ef30b100a2838bff293 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Mar 2024 15:46:00 +0000 Subject: [PATCH 05/73] fix: bump actions/github-script from 6 to 7 (#626) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/github-script](https://github.com/actions/github-script) from 6 to 7.
Release notes

Sourced from actions/github-script's releases.

v7.0.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/github-script/compare/v6.4.1...v7.0.0

v6.4.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/github-script/compare/v6.4.0...v6.4.1

v6.4.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/github-script/compare/v6.3.3...v6.4.0

v6.3.3

What's Changed

New Contributors

Full Changelog: https://github.com/actions/github-script/compare/v6.3.2...v6.3.3

v6.3.2

What's Changed

... (truncated)

Commits
  • e69ef54 Merge pull request #425 from actions/joshmgross/node-20
  • ee0914b Update licenses
  • d6fc56f Use @types/node for Node 20
  • 384d6cf Fix quotations in tests
  • 8472492 Only validate GraphQL previews
  • 84903f5 Remove node-fetch from type
  • 5349cf9 Merge branch 'main' into joshmgross/node-20
  • ecae9eb Merge pull request #402 from typed-actions/export-types
  • 044ebbb Merge branch 'main' into export-types
  • 6b5d3ea Merge pull request #429 from robandpdx/add-base-url-option
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/github-script&package-manager=github_actions&previous-version=6&new-version=7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) You can trigger a rebase of this PR by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
> **Note** > Automatic rebases have been disabled on this pull request as it has been open for over 30 days. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> --- .github/workflows/get-changed-module.yml | 2 +- .github/workflows/on-push-main.yml | 2 +- .github/workflows/publish-module-index.yml | 4 ++-- .github/workflows/publish-module.yml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/get-changed-module.yml b/.github/workflows/get-changed-module.yml index 9af73ae4ea..696faa3062 100644 --- a/.github/workflows/get-changed-module.yml +++ b/.github/workflows/get-changed-module.yml @@ -17,7 +17,7 @@ jobs: uses: actions/checkout@v4 - name: Get changed module - uses: actions/github-script@v6 + uses: actions/github-script@v7 id: get-changed-module with: result-encoding: string diff --git a/.github/workflows/on-push-main.yml b/.github/workflows/on-push-main.yml index 11cacacd4b..1e862b6a18 100644 --- a/.github/workflows/on-push-main.yml +++ b/.github/workflows/on-push-main.yml @@ -35,7 +35,7 @@ jobs: - name: Create tag id: create-tag - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: result-encoding: string script: | diff --git a/.github/workflows/publish-module-index.yml b/.github/workflows/publish-module-index.yml index fb90df0210..219696d3cf 100644 --- a/.github/workflows/publish-module-index.yml +++ b/.github/workflows/publish-module-index.yml @@ -30,7 +30,7 @@ jobs: run: npm ci - name: Generate moduleIndex.json - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: script: | const script = require("./scripts/github-actions/generate-module-index-data.js") @@ -71,7 +71,7 @@ jobs: name: moduleIndex.json - name: Generate index.md - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: script: | const script = require("./scripts/github-actions/generate-module-index-md.js") diff --git a/.github/workflows/publish-module.yml b/.github/workflows/publish-module.yml index fe82d54fce..10271adcae 100644 --- a/.github/workflows/publish-module.yml +++ b/.github/workflows/publish-module.yml @@ -37,7 +37,7 @@ jobs: - name: Parse tag id: parse-tag - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: result-encoding: string script: | From e0a236e0ac7036a6232eae7743505d1aeabad10c Mon Sep 17 00:00:00 2001 From: Erika Gressi <56914614+eriqua@users.noreply.github.com> Date: Tue, 12 Mar 2024 15:56:03 +0000 Subject: [PATCH 06/73] fix: web/static-site update to enforce publish with source (#1253) ## Description - Update template to enforce publish with source - Fix bug in workflow trigger - Update identity variable to fix Warning BCP036 thrown by compile ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.web.static-site](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.web.static-site.yml/badge.svg?branch=fix%2Feriqua%2Fstatic-site)](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.web.static-site.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [ ] Azure Verified Module updates: - [ ] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [ ] I'm sure there are no other open Pull Requests for the same update/change - [ ] I have run `Set-AVMModule` locally to generate the supporting module files. - [ ] My corresponding pipelines / checks run clean and green without any errors or warnings --- .github/workflows/avm.res.web.static-site.yml | 2 +- avm/res/web/static-site/README.md | 8 ++++---- avm/res/web/static-site/main.bicep | 4 ++-- avm/res/web/static-site/main.json | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/avm.res.web.static-site.yml b/.github/workflows/avm.res.web.static-site.yml index e55d55bcfc..5423969e4b 100644 --- a/.github/workflows/avm.res.web.static-site.yml +++ b/.github/workflows/avm.res.web.static-site.yml @@ -27,7 +27,7 @@ on: - ".github/actions/templates/avm-**" - ".github/workflows/avm.template.module.yml" - ".github/workflows/avm.res.web.static-site.yml" - - "avm/res/web/serverfarm/**" + - "avm/res/web/static-site/**" - "avm/utilities/pipelines/**" - "!*/**/README.md" diff --git a/avm/res/web/static-site/README.md b/avm/res/web/static-site/README.md index fd130bc092..2c5d5d71f5 100644 --- a/avm/res/web/static-site/README.md +++ b/avm/res/web/static-site/README.md @@ -437,7 +437,7 @@ module staticSite 'br/public:avm/res/web/static-site:' = { | Parameter | Type | Description | | :-- | :-- | :-- | -| [`name`](#parameter-name) | string | Name of the static site. | +| [`name`](#parameter-name) | string | The name of the static site. | **Optional parameters** @@ -460,14 +460,14 @@ module staticSite 'br/public:avm/res/web/static-site:' = { | [`repositoryToken`](#parameter-repositorytoken) | securestring | The Personal Access Token for accessing the GitHub repository. | | [`repositoryUrl`](#parameter-repositoryurl) | string | The name of the GitHub repository. | | [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | -| [`sku`](#parameter-sku) | string | Type of static site to deploy. | +| [`sku`](#parameter-sku) | string | The service tier and name of the resource SKU. | | [`stagingEnvironmentPolicy`](#parameter-stagingenvironmentpolicy) | string | State indicating whether staging environments are allowed or not allowed for a static web app. | | [`tags`](#parameter-tags) | object | Tags of the resource. | | [`templateProperties`](#parameter-templateproperties) | object | Template Options for the static site. | ### Parameter: `name` -Name of the static site. +The name of the static site. - Required: Yes - Type: string @@ -1063,7 +1063,7 @@ The principal type of the assigned principal ID. ### Parameter: `sku` -Type of static site to deploy. +The service tier and name of the resource SKU. - Required: No - Type: string diff --git a/avm/res/web/static-site/main.bicep b/avm/res/web/static-site/main.bicep index 78688b9023..92bb14bee0 100644 --- a/avm/res/web/static-site/main.bicep +++ b/avm/res/web/static-site/main.bicep @@ -2,7 +2,7 @@ metadata name = 'Static Web Apps' metadata description = 'This module deploys a Static Web App.' metadata owner = 'Azure/module-maintainers' -@description('Required. Name of the static site.') +@description('Required. The name of the static site.') @minLength(1) @maxLength(40) param name string @@ -11,7 +11,7 @@ param name string 'Free' 'Standard' ]) -@description('Optional. Type of static site to deploy.') +@description('Optional. The service tier and name of the resource SKU.') param sku string = 'Free' @description('Optional. False if config file is locked for this static web app; otherwise, true.') diff --git a/avm/res/web/static-site/main.json b/avm/res/web/static-site/main.json index b226d1b32c..6d473d52c2 100644 --- a/avm/res/web/static-site/main.json +++ b/avm/res/web/static-site/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "15307408528388407015" + "templateHash": "18245734514085730321" }, "name": "Static Web Apps", "description": "This module deploys a Static Web App.", @@ -317,7 +317,7 @@ "minLength": 1, "maxLength": 40, "metadata": { - "description": "Required. Name of the static site." + "description": "Required. The name of the static site." } }, "sku": { @@ -328,7 +328,7 @@ "Standard" ], "metadata": { - "description": "Optional. Type of static site to deploy." + "description": "Optional. The service tier and name of the resource SKU." } }, "allowConfigFileUpdates": { From dea7c94adcdd26242a1dbef230bf3eaa4c329d80 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Mar 2024 16:01:51 +0000 Subject: [PATCH 07/73] fix: bump actions/setup-node from 3 to 4 (#588) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3 to 4.
Release notes

Sourced from actions/setup-node's releases.

v4.0.0

What's Changed

In scope of this release we changed version of node runtime for action from node16 to node20 and updated dependencies in actions/setup-node#866

Besides, release contains such changes as:

New Contributors

Full Changelog: https://github.com/actions/setup-node/compare/v3...v4.0.0

v3.8.2

What's Changed

Full Changelog: https://github.com/actions/setup-node/compare/v3...v3.8.2

v3.8.1

What's Changed

In scope of this release, the filter was removed within the cache-save step by @​dmitry-shibanov in actions/setup-node#831. It is filtered and checked in the toolkit/cache library.

Full Changelog: https://github.com/actions/setup-node/compare/v3...v3.8.1

v3.8.0

What's Changed

Bug fixes:

Feature implementations:

Documentation changes:

Update dependencies:

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-node&package-manager=github_actions&previous-version=3&new-version=4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) You can trigger a rebase of this PR by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
> **Note** > Automatic rebases have been disabled on this pull request as it has been open for over 30 days. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> --- .github/workflows/fork-on-push-format-workflow.yml | 2 +- .github/workflows/on-pull-request.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/fork-on-push-format-workflow.yml b/.github/workflows/fork-on-push-format-workflow.yml index 64310a430e..263a03088f 100644 --- a/.github/workflows/fork-on-push-format-workflow.yml +++ b/.github/workflows/fork-on-push-format-workflow.yml @@ -31,7 +31,7 @@ jobs: token: ${{ secrets.WORKFLOW_PAT }} # A WORKFLOW_PAT must be used to re-trigger workflows after commit. This PAT must have the workflow scope. This is not generally recommended. - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: "16" diff --git a/.github/workflows/on-pull-request.yml b/.github/workflows/on-pull-request.yml index ba3b96b475..2745ead0e1 100644 --- a/.github/workflows/on-pull-request.yml +++ b/.github/workflows/on-pull-request.yml @@ -69,7 +69,7 @@ jobs: uses: actions/checkout@v4 - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: "16" From 9ec886e91d81501b4970610dbd44484e7eb271a9 Mon Sep 17 00:00:00 2001 From: Erika Gressi <56914614+eriqua@users.noreply.github.com> Date: Tue, 12 Mar 2024 16:07:34 +0000 Subject: [PATCH 08/73] fix: `avm/res/network/ip-group` and `avm/res/network/private-link-service` patch update to enforce publish with source (#1258) ## Description Minor parameter description update to enforce new patch version to be published with source ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.network.private-link-service](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.network.private-link-service.yml/badge.svg?branch=fix%2Feriqua%2Fnetwork)](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.network.private-link-service.yml) | | [![avm.res.network.ip-group](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.network.ip-group.yml/badge.svg?branch=fix%2Feriqua%2Fnetwork)](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.network.ip-group.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [ ] Azure Verified Module updates: - [ ] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [ ] I'm sure there are no other open Pull Requests for the same update/change - [ ] I have run `Set-AVMModule` locally to generate the supporting module files. - [ ] My corresponding pipelines / checks run clean and green without any errors or warnings --- avm/res/network/ip-group/README.md | 8 ++++---- avm/res/network/ip-group/main.bicep | 4 ++-- avm/res/network/ip-group/main.json | 6 +++--- avm/res/network/private-link-service/README.md | 4 ++-- avm/res/network/private-link-service/main.bicep | 2 +- avm/res/network/private-link-service/main.json | 4 ++-- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/avm/res/network/ip-group/README.md b/avm/res/network/ip-group/README.md index 0a5fc6ec51..42ce567b3d 100644 --- a/avm/res/network/ip-group/README.md +++ b/avm/res/network/ip-group/README.md @@ -272,14 +272,14 @@ module ipGroup 'br/public:avm/res/network/ip-group:' = { | Parameter | Type | Description | | :-- | :-- | :-- | -| [`name`](#parameter-name) | string | The name of the ipGroups. | +| [`name`](#parameter-name) | string | The name of the IP Group. | **Optional parameters** | Parameter | Type | Description | | :-- | :-- | :-- | | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | -| [`ipAddresses`](#parameter-ipaddresses) | array | IpAddresses/IpAddressPrefixes in the IpGroups resource. | +| [`ipAddresses`](#parameter-ipaddresses) | array | IpAddresses/IpAddressPrefixes in the IP Group resource. | | [`location`](#parameter-location) | string | Location for all resources. | | [`lock`](#parameter-lock) | object | The lock settings of the service. | | [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | @@ -287,7 +287,7 @@ module ipGroup 'br/public:avm/res/network/ip-group:' = { ### Parameter: `name` -The name of the ipGroups. +The name of the IP Group. - Required: Yes - Type: string @@ -302,7 +302,7 @@ Enable/Disable usage telemetry for module. ### Parameter: `ipAddresses` -IpAddresses/IpAddressPrefixes in the IpGroups resource. +IpAddresses/IpAddressPrefixes in the IP Group resource. - Required: No - Type: array diff --git a/avm/res/network/ip-group/main.bicep b/avm/res/network/ip-group/main.bicep index a0ac6abed3..9232554ce1 100644 --- a/avm/res/network/ip-group/main.bicep +++ b/avm/res/network/ip-group/main.bicep @@ -2,14 +2,14 @@ metadata name = 'IP Groups' metadata description = 'This module deploys an IP Group.' metadata owner = 'Azure/module-maintainers' -@description('Required. The name of the ipGroups.') +@description('Required. The name of the IP Group.') @minLength(1) param name string @description('Optional. Location for all resources.') param location string = resourceGroup().location -@description('Optional. IpAddresses/IpAddressPrefixes in the IpGroups resource.') +@description('Optional. IpAddresses/IpAddressPrefixes in the IP Group resource.') param ipAddresses array = [] @description('Optional. The lock settings of the service.') diff --git a/avm/res/network/ip-group/main.json b/avm/res/network/ip-group/main.json index 0d02c1d3c2..c190237042 100644 --- a/avm/res/network/ip-group/main.json +++ b/avm/res/network/ip-group/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "6351514954757717512" + "templateHash": "3252011302585807507" }, "name": "IP Groups", "description": "This module deploys an IP Group.", @@ -110,7 +110,7 @@ "type": "string", "minLength": 1, "metadata": { - "description": "Required. The name of the ipGroups." + "description": "Required. The name of the IP Group." } }, "location": { @@ -124,7 +124,7 @@ "type": "array", "defaultValue": [], "metadata": { - "description": "Optional. IpAddresses/IpAddressPrefixes in the IpGroups resource." + "description": "Optional. IpAddresses/IpAddressPrefixes in the IP Group resource." } }, "lock": { diff --git a/avm/res/network/private-link-service/README.md b/avm/res/network/private-link-service/README.md index a37ec6ce9d..192f187d73 100644 --- a/avm/res/network/private-link-service/README.md +++ b/avm/res/network/private-link-service/README.md @@ -440,7 +440,7 @@ module privateLinkService 'br/public:avm/res/network/private-link-service: Date: Tue, 12 Mar 2024 17:11:33 +0100 Subject: [PATCH 09/73] feat: New Module avm/res/network/azure-firewall, migrated from CARML. (#1079) ## Description Migration of Azure firewall module from CARML ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.network.azure-firewall](https://github.com/rahalan/bicep-registry-modules/actions/workflows/avm.res.network.azure-firewall.yml/badge.svg?branch=users%2Frahalan%2FAddAFW)](https://github.com/rahalan/bicep-registry-modules/actions/workflows/avm.res.network.azure-firewall.yml) | ## Type of Change - [X] I have run deployment tests locally to ensure the module is deployable. --- .github/CODEOWNERS | 2 +- .github/ISSUE_TEMPLATE/avm_module_issue.yml | 2 +- .../avm.res.network.azure-firewall.yml | 85 + avm/res/network/azure-firewall/README.md | 1538 ++++++++++++++ avm/res/network/azure-firewall/main.bicep | 387 ++++ avm/res/network/azure-firewall/main.json | 1784 +++++++++++++++++ .../tests/e2e/addpip/dependencies.bicep | 70 + .../tests/e2e/addpip/main.test.bicep | 75 + .../tests/e2e/custompip/dependencies.bicep | 41 + .../tests/e2e/custompip/main.test.bicep | 99 + .../tests/e2e/defaults/dependencies.bicep | 29 + .../tests/e2e/defaults/main.test.bicep | 56 + .../tests/e2e/hubcommon/dependencies.bicep | 46 + .../tests/e2e/hubcommon/main.test.bicep | 64 + .../tests/e2e/hubmin/dependencies.bicep | 32 + .../tests/e2e/hubmin/main.test.bicep | 62 + .../tests/e2e/max/dependencies.bicep | 64 + .../tests/e2e/max/main.test.bicep | 199 ++ .../tests/e2e/waf-aligned/dependencies.bicep | 64 + .../tests/e2e/waf-aligned/main.test.bicep | 178 ++ avm/res/network/azure-firewall/version.json | 7 + 21 files changed, 4882 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/avm.res.network.azure-firewall.yml create mode 100644 avm/res/network/azure-firewall/README.md create mode 100644 avm/res/network/azure-firewall/main.bicep create mode 100644 avm/res/network/azure-firewall/main.json create mode 100644 avm/res/network/azure-firewall/tests/e2e/addpip/dependencies.bicep create mode 100644 avm/res/network/azure-firewall/tests/e2e/addpip/main.test.bicep create mode 100644 avm/res/network/azure-firewall/tests/e2e/custompip/dependencies.bicep create mode 100644 avm/res/network/azure-firewall/tests/e2e/custompip/main.test.bicep create mode 100644 avm/res/network/azure-firewall/tests/e2e/defaults/dependencies.bicep create mode 100644 avm/res/network/azure-firewall/tests/e2e/defaults/main.test.bicep create mode 100644 avm/res/network/azure-firewall/tests/e2e/hubcommon/dependencies.bicep create mode 100644 avm/res/network/azure-firewall/tests/e2e/hubcommon/main.test.bicep create mode 100644 avm/res/network/azure-firewall/tests/e2e/hubmin/dependencies.bicep create mode 100644 avm/res/network/azure-firewall/tests/e2e/hubmin/main.test.bicep create mode 100644 avm/res/network/azure-firewall/tests/e2e/max/dependencies.bicep create mode 100644 avm/res/network/azure-firewall/tests/e2e/max/main.test.bicep create mode 100644 avm/res/network/azure-firewall/tests/e2e/waf-aligned/dependencies.bicep create mode 100644 avm/res/network/azure-firewall/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/res/network/azure-firewall/version.json diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 15756380a8..28f99373e3 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -78,7 +78,7 @@ #/avm/res/network/application-gateway/ @Azure/avm-res-network-applicationgateway-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/network/application-gateway-web-application-firewall-policy/ @Azure/avm-res-network-applicationgatewaywebapplicationfirewallpolicy-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/network/application-security-group/ @Azure/avm-res-network-applicationsecuritygroup-module-owners-bicep @Azure/avm-core-team-technical-bicep -#/avm/res/network/azure-firewall/ @Azure/avm-res-network-azurefirewall-module-owners-bicep @Azure/avm-core-team-technical-bicep +/avm/res/network/azure-firewall/ @Azure/avm-res-network-azurefirewall-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/network/bastion-host/ @Azure/avm-res-network-bastionhost-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/network/connection/ @Azure/avm-res-network-connection-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/network/ddos-protection-plan/ @Azure/avm-res-network-ddosprotectionplan-module-owners-bicep @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 9a3bd7409d..8719866367 100644 --- a/.github/ISSUE_TEMPLATE/avm_module_issue.yml +++ b/.github/ISSUE_TEMPLATE/avm_module_issue.yml @@ -112,7 +112,7 @@ body: # - "avm/res/network/application-gateway" # - "avm/res/network/application-gateway-web-application-firewall-policy" - "avm/res/network/application-security-group" - # - "avm/res/network/azure-firewall" + - "avm/res/network/azure-firewall" - "avm/res/network/bastion-host" - "avm/res/network/connection" - "avm/res/network/ddos-protection-plan" diff --git a/.github/workflows/avm.res.network.azure-firewall.yml b/.github/workflows/avm.res.network.azure-firewall.yml new file mode 100644 index 0000000000..7e6a0195c1 --- /dev/null +++ b/.github/workflows/avm.res.network.azure-firewall.yml @@ -0,0 +1,85 @@ +name: "avm.res.network.azure-firewall" + +on: + schedule: + - cron: "0 12 1/15 * *" # Bi-Weekly Test (on 1st & 15th of month) + 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 + push: + branches: + - main + paths: + - ".github/actions/templates/avm-**" + - ".github/workflows/avm.template.module.yml" + - ".github/workflows/avm.res.network.azure-firewall.yml" + - "avm/res/network/azure-firewall/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/network/azure-firewall" + workflowPath: ".github/workflows/avm.res.network.azure-firewall.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-latest + name: "Initialize pipeline" + steps: + - name: "Checkout" + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: "Set input parameters to output variables" + id: get-workflow-param + uses: ./.github/actions/templates/avm-getWorkflowInput + with: + workflowPath: "${{ env.workflowPath}}" + - name: "Get module test file paths" + id: get-module-test-file-paths + uses: ./.github/actions/templates/avm-getModuleTestFiles + with: + modulePath: "${{ env.modulePath }}" + outputs: + workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }} + moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} + psRuleModuleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.psRuleModuleTestFilePaths }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Run" + permissions: + id-token: write # For OIDC + contents: write # For release tags + needs: + - job_initialize_pipeline + uses: ./.github/workflows/avm.template.module.yml + with: + workflowInput: "${{ needs.job_initialize_pipeline.outputs.workflowInput }}" + moduleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.moduleTestFilePaths }}" + psRuleModuleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.psRuleModuleTestFilePaths }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit diff --git a/avm/res/network/azure-firewall/README.md b/avm/res/network/azure-firewall/README.md new file mode 100644 index 0000000000..fbb0980ca3 --- /dev/null +++ b/avm/res/network/azure-firewall/README.md @@ -0,0 +1,1538 @@ +# Azure Firewalls `[Microsoft.Network/azureFirewalls]` + +This module deploys an Azure Firewall. + +## Navigation + +- [Resource Types](#Resource-Types) +- [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` | [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/publicIPAddresses` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/publicIPAddresses) | + +## 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/res/network/azure-firewall:`. + +- [Add-PIP](#example-1-add-pip) +- [Custom-PIP](#example-2-custom-pip) +- [Using only defaults](#example-3-using-only-defaults) +- [Hub-commom](#example-4-hub-commom) +- [Hub-min](#example-5-hub-min) +- [Using large parameter set](#example-6-using-large-parameter-set) +- [WAF-aligned](#example-7-waf-aligned) + +### Example 1: _Add-PIP_ + +This instance deploys the module and attaches an existing public IP address. + + +
+ +via Bicep module + +```bicep +module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-nafaddpip' + params: { + // Required parameters + name: 'nafaddpip001' + // Non-required parameters + additionalPublicIpConfigurations: [ + { + name: 'ipConfig01' + publicIPAddressResourceId: '' + } + ] + azureSkuTier: 'Basic' + location: '' + managementIPAddressObject: { + publicIPAllocationMethod: 'Static' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + } + virtualNetworkId: '' + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "nafaddpip001" + }, + // Non-required parameters + "additionalPublicIpConfigurations": { + "value": [ + { + "name": "ipConfig01", + "publicIPAddressResourceId": "" + } + ] + }, + "azureSkuTier": { + "value": "Basic" + }, + "location": { + "value": "" + }, + "managementIPAddressObject": { + "value": { + "publicIPAllocationMethod": "Static", + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ] + } + }, + "virtualNetworkId": { + "value": "" + } + } +} +``` + +
+

+ +### Example 2: _Custom-PIP_ + +This instance deploys the module and will create a public IP address. + + +

+ +via Bicep module + +```bicep +module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-nafcstpip' + params: { + // Required parameters + name: 'nafcstpip001' + // Non-required parameters + location: '' + publicIPAddressObject: { + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + name: 'new-pip-nafcstpip' + publicIPAllocationMethod: 'Static' + publicIPPrefixResourceId: '' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + skuName: 'Standard' + skuTier: 'Regional' + } + virtualNetworkId: '' + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "nafcstpip001" + }, + // Non-required parameters + "location": { + "value": "" + }, + "publicIPAddressObject": { + "value": { + "diagnosticSettings": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ], + "name": "new-pip-nafcstpip", + "publicIPAllocationMethod": "Static", + "publicIPPrefixResourceId": "", + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ], + "skuName": "Standard", + "skuTier": "Regional" + } + }, + "virtualNetworkId": { + "value": "" + } + } +} +``` + +
+

+ +### Example 3: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. + + +

+ +via Bicep module + +```bicep +module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-nafmin' + params: { + // Required parameters + name: 'nafmin001' + // Non-required parameters + location: '' + virtualNetworkId: '' + } +} +``` + +
+

+ +

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

+ +### Example 4: _Hub-commom_ + +This instance deploys the module a vWAN in a typical hub setting. + + +

+ +via Bicep module + +```bicep +module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-nafhubcom' + params: { + // Required parameters + name: 'nafhubcom001' + // Non-required parameters + firewallPolicyId: '' + hubIPAddresses: { + publicIPs: { + count: 1 + } + } + location: '' + virtualHubId: '' + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "nafhubcom001" + }, + // Non-required parameters + "firewallPolicyId": { + "value": "" + }, + "hubIPAddresses": { + "value": { + "publicIPs": { + "count": 1 + } + } + }, + "location": { + "value": "" + }, + "virtualHubId": { + "value": "" + } + } +} +``` + +
+

+ +### Example 5: _Hub-min_ + +This instance deploys the module a vWAN minimum hub setting. + + +

+ +via Bicep module + +```bicep +module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-nafhubmin' + params: { + // Required parameters + name: 'nafhubmin001' + // Non-required parameters + hubIPAddresses: { + publicIPs: { + count: 1 + } + } + location: '' + virtualHubId: '' + } +} +``` + +
+

+ +

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

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

+ +via Bicep module + +```bicep +module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-nafmax' + params: { + // Required parameters + name: 'nafmax001' + // Non-required parameters + applicationRuleCollections: [ + { + name: 'allow-app-rules' + properties: { + action: { + type: 'allow' + } + priority: 100 + rules: [ + { + fqdnTags: [ + 'AppServiceEnvironment' + 'WindowsUpdate' + ] + name: 'allow-ase-tags' + protocols: [ + { + port: '80' + protocolType: 'HTTP' + } + { + port: '443' + protocolType: 'HTTPS' + } + ] + sourceAddresses: [ + '*' + ] + } + { + name: 'allow-ase-management' + protocols: [ + { + port: '80' + protocolType: 'HTTP' + } + { + port: '443' + protocolType: 'HTTPS' + } + ] + sourceAddresses: [ + '*' + ] + targetFqdns: [ + 'bing.com' + ] + } + ] + } + } + ] + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + networkRuleCollections: [ + { + name: 'allow-network-rules' + properties: { + action: { + type: 'allow' + } + priority: 100 + rules: [ + { + destinationAddresses: [ + '*' + ] + destinationPorts: [ + '12000' + '123' + ] + name: 'allow-ntp' + protocols: [ + 'Any' + ] + sourceAddresses: [ + '*' + ] + } + ] + } + } + ] + publicIPResourceID: '' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + virtualNetworkId: '' + zones: [ + '1' + '2' + '3' + ] + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "nafmax001" + }, + // Non-required parameters + "applicationRuleCollections": { + "value": [ + { + "name": "allow-app-rules", + "properties": { + "action": { + "type": "allow" + }, + "priority": 100, + "rules": [ + { + "fqdnTags": [ + "AppServiceEnvironment", + "WindowsUpdate" + ], + "name": "allow-ase-tags", + "protocols": [ + { + "port": "80", + "protocolType": "HTTP" + }, + { + "port": "443", + "protocolType": "HTTPS" + } + ], + "sourceAddresses": [ + "*" + ] + }, + { + "name": "allow-ase-management", + "protocols": [ + { + "port": "80", + "protocolType": "HTTP" + }, + { + "port": "443", + "protocolType": "HTTPS" + } + ], + "sourceAddresses": [ + "*" + ], + "targetFqdns": [ + "bing.com" + ] + } + ] + } + } + ] + }, + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "networkRuleCollections": { + "value": [ + { + "name": "allow-network-rules", + "properties": { + "action": { + "type": "allow" + }, + "priority": 100, + "rules": [ + { + "destinationAddresses": [ + "*" + ], + "destinationPorts": [ + "12000", + "123" + ], + "name": "allow-ntp", + "protocols": [ + "Any" + ], + "sourceAddresses": [ + "*" + ] + } + ] + } + } + ] + }, + "publicIPResourceID": { + "value": "" + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + "virtualNetworkId": { + "value": "" + }, + "zones": { + "value": [ + "1", + "2", + "3" + ] + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-nafwaf' + params: { + // Required parameters + name: 'nafwaf001' + // Non-required parameters + applicationRuleCollections: [ + { + name: 'allow-app-rules' + properties: { + action: { + type: 'allow' + } + priority: 100 + rules: [ + { + fqdnTags: [ + 'AppServiceEnvironment' + 'WindowsUpdate' + ] + name: 'allow-ase-tags' + protocols: [ + { + port: '80' + protocolType: 'HTTP' + } + { + port: '443' + protocolType: 'HTTPS' + } + ] + sourceAddresses: [ + '*' + ] + } + { + name: 'allow-ase-management' + protocols: [ + { + port: '80' + protocolType: 'HTTP' + } + { + port: '443' + protocolType: 'HTTPS' + } + ] + sourceAddresses: [ + '*' + ] + targetFqdns: [ + 'bing.com' + ] + } + ] + } + } + ] + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + location: '' + networkRuleCollections: [ + { + name: 'allow-network-rules' + properties: { + action: { + type: 'allow' + } + priority: 100 + rules: [ + { + destinationAddresses: [ + '*' + ] + destinationPorts: [ + '12000' + '123' + ] + name: 'allow-ntp' + protocols: [ + 'Any' + ] + sourceAddresses: [ + '*' + ] + } + ] + } + } + ] + publicIPResourceID: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + virtualNetworkId: '' + zones: [ + '1' + '2' + '3' + ] + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "nafwaf001" + }, + // Non-required parameters + "applicationRuleCollections": { + "value": [ + { + "name": "allow-app-rules", + "properties": { + "action": { + "type": "allow" + }, + "priority": 100, + "rules": [ + { + "fqdnTags": [ + "AppServiceEnvironment", + "WindowsUpdate" + ], + "name": "allow-ase-tags", + "protocols": [ + { + "port": "80", + "protocolType": "HTTP" + }, + { + "port": "443", + "protocolType": "HTTPS" + } + ], + "sourceAddresses": [ + "*" + ] + }, + { + "name": "allow-ase-management", + "protocols": [ + { + "port": "80", + "protocolType": "HTTP" + }, + { + "port": "443", + "protocolType": "HTTPS" + } + ], + "sourceAddresses": [ + "*" + ], + "targetFqdns": [ + "bing.com" + ] + } + ] + } + } + ] + }, + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "location": { + "value": "" + }, + "networkRuleCollections": { + "value": [ + { + "name": "allow-network-rules", + "properties": { + "action": { + "type": "allow" + }, + "priority": 100, + "rules": [ + { + "destinationAddresses": [ + "*" + ], + "destinationPorts": [ + "12000", + "123" + ], + "name": "allow-ntp", + "protocols": [ + "Any" + ], + "sourceAddresses": [ + "*" + ] + } + ] + } + } + ] + }, + "publicIPResourceID": { + "value": "" + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + "virtualNetworkId": { + "value": "" + }, + "zones": { + "value": [ + "1", + "2", + "3" + ] + } + } +} +``` + +
+

+ + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the Azure Firewall. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`hubIPAddresses`](#parameter-hubipaddresses) | object | IP addresses associated with AzureFirewall. Required if `virtualHubId` is supplied. | +| [`virtualHubId`](#parameter-virtualhubid) | string | The virtualHub resource ID to which the firewall belongs. Required if `virtualNetworkId` is empty. | +| [`virtualNetworkId`](#parameter-virtualnetworkid) | string | Shared services Virtual Network resource ID. The virtual network ID containing AzureFirewallSubnet. If a Public IP is not provided, then the Public IP that is created as part of this module will be applied with the subnet provided in this variable. Required if `virtualHubId` is empty. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`additionalPublicIpConfigurations`](#parameter-additionalpublicipconfigurations) | array | This is to add any additional Public IP configurations on top of the Public IP with subnet IP configuration. | +| [`applicationRuleCollections`](#parameter-applicationrulecollections) | array | Collection of application rule collections used by Azure Firewall. | +| [`azureSkuTier`](#parameter-azureskutier) | string | Tier of an Azure Firewall. | +| [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`firewallPolicyId`](#parameter-firewallpolicyid) | string | Resource ID of the Firewall Policy that should be attached. | +| [`location`](#parameter-location) | string | Location for all resources. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`managementIPAddressObject`](#parameter-managementipaddressobject) | object | Specifies the properties of the Management Public IP to create and be used by Azure Firewall. If it's not provided and managementIPResourceID is empty, a '-mip' suffix will be appended to the Firewall's name. | +| [`managementIPResourceID`](#parameter-managementipresourceid) | string | The Management Public IP resource ID to associate to the AzureFirewallManagementSubnet. If empty, then the Management Public IP that is created as part of this module will be applied to the AzureFirewallManagementSubnet. | +| [`natRuleCollections`](#parameter-natrulecollections) | array | Collection of NAT rule collections used by Azure Firewall. | +| [`networkRuleCollections`](#parameter-networkrulecollections) | array | Collection of network rule collections used by Azure Firewall. | +| [`publicIPAddressObject`](#parameter-publicipaddressobject) | object | Specifies the properties of the Public IP to create and be used by the Firewall, if no existing public IP was provided. | +| [`publicIPResourceID`](#parameter-publicipresourceid) | string | The Public IP resource ID to associate to the AzureFirewallSubnet. If empty, then the Public IP that is created as part of this module will be applied to the AzureFirewallSubnet. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`tags`](#parameter-tags) | object | Tags of the Azure Firewall resource. | +| [`threatIntelMode`](#parameter-threatintelmode) | string | The operation mode for Threat Intel. | +| [`zones`](#parameter-zones) | array | Zone numbers e.g. 1,2,3. | + +### Parameter: `name` + +Name of the Azure Firewall. + +- Required: Yes +- Type: string + +### Parameter: `hubIPAddresses` + +IP addresses associated with AzureFirewall. Required if `virtualHubId` is supplied. + +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `virtualHubId` + +The virtualHub resource ID to which the firewall belongs. Required if `virtualNetworkId` is empty. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `virtualNetworkId` + +Shared services Virtual Network resource ID. The virtual network ID containing AzureFirewallSubnet. If a Public IP is not provided, then the Public IP that is created as part of this module will be applied with the subnet provided in this variable. Required if `virtualHubId` is empty. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `additionalPublicIpConfigurations` + +This is to add any additional Public IP configurations on top of the Public IP with subnet IP configuration. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `applicationRuleCollections` + +Collection of application rule collections used by Azure Firewall. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `azureSkuTier` + +Tier of an Azure Firewall. + +- Required: No +- Type: string +- Default: `'Standard'` +- Allowed: + ```Bicep + [ + 'Basic' + 'Premium' + 'Standard' + ] + ``` + +### Parameter: `diagnosticSettings` + +The diagnostic settings of the service. + +- Required: No +- Type: array + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`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 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. | +| [`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. | + +### Parameter: `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: `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: `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: `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. + +- Required: No +- Type: string + +### Parameter: `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-diagnosticsettingsmetriccategoriescategory) | 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-diagnosticsettingsmetriccategoriesenabled) | bool | Enable or disable the category explicitly. Default is `true`. | + +### Parameter: `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: `diagnosticSettings.metricCategories.enabled` + +Enable or disable the category explicitly. Default is `true`. + +- Required: No +- Type: bool + +### Parameter: `diagnosticSettings.name` + +The name of diagnostic setting. + +- Required: No +- Type: string + +### Parameter: `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: `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: `enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `firewallPolicyId` + +Resource ID of the Firewall Policy that should be attached. + +- Required: No +- Type: string +- Default: `''` + +### 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: `managementIPAddressObject` + +Specifies the properties of the Management Public IP to create and be used by Azure Firewall. If it's not provided and managementIPResourceID is empty, a '-mip' suffix will be appended to the Firewall's name. + +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `managementIPResourceID` + +The Management Public IP resource ID to associate to the AzureFirewallManagementSubnet. If empty, then the Management Public IP that is created as part of this module will be applied to the AzureFirewallManagementSubnet. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `natRuleCollections` + +Collection of NAT rule collections used by Azure Firewall. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `networkRuleCollections` + +Collection of network rule collections used by Azure Firewall. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `publicIPAddressObject` + +Specifies the properties of the Public IP to create and be used by the Firewall, if no existing public IP was provided. + +- Required: No +- Type: object +- Default: + ```Bicep + { + name: '[format(\'{0}-pip\', parameters(\'name\'))]' + } + ``` + +### Parameter: `publicIPResourceID` + +The Public IP resource ID to associate to the AzureFirewallSubnet. If empty, then the Public IP that is created as part of this module will be applied to the AzureFirewallSubnet. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**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. | +| [`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.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `tags` + +Tags of the Azure Firewall resource. + +- Required: No +- Type: object + +### Parameter: `threatIntelMode` + +The operation mode for Threat Intel. + +- Required: No +- Type: string +- Default: `'Deny'` +- Allowed: + ```Bicep + [ + 'Alert' + 'Deny' + 'Off' + ] + ``` + +### Parameter: `zones` + +Zone numbers e.g. 1,2,3. + +- Required: No +- Type: array +- Default: + ```Bicep + [ + '1' + '2' + '3' + ] + ``` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `applicationRuleCollections` | array | List of Application Rule Collections. | +| `ipConfAzureFirewallSubnet` | object | The Public IP configuration object for the Azure Firewall Subnet. | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the Azure Firewall. | +| `natRuleCollections` | array | Collection of NAT rule collections used by Azure Firewall. | +| `networkRuleCollections` | array | List of Network Rule Collections. | +| `privateIp` | string | The private IP of the Azure firewall. | +| `resourceGroupName` | string | The resource group the Azure firewall was deployed into. | +| `resourceId` | string | The resource ID of the Azure Firewall. | + +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other CARML 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/network/public-ip-address: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/azure-firewall/main.bicep b/avm/res/network/azure-firewall/main.bicep new file mode 100644 index 0000000000..df64924d31 --- /dev/null +++ b/avm/res/network/azure-firewall/main.bicep @@ -0,0 +1,387 @@ +metadata name = 'Azure Firewalls' +metadata description = 'This module deploys an Azure Firewall.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. Name of the Azure Firewall.') +param name string + +@description('Optional. Tier of an Azure Firewall.') +@allowed([ + 'Basic' + 'Standard' + 'Premium' +]) +param azureSkuTier string = 'Standard' + +@description('Conditional. Shared services Virtual Network resource ID. The virtual network ID containing AzureFirewallSubnet. If a Public IP is not provided, then the Public IP that is created as part of this module will be applied with the subnet provided in this variable. Required if `virtualHubId` is empty.') +param virtualNetworkId string = '' + +@description('Optional. The Public IP resource ID to associate to the AzureFirewallSubnet. If empty, then the Public IP that is created as part of this module will be applied to the AzureFirewallSubnet.') +param publicIPResourceID string = '' + +@description('Optional. This is to add any additional Public IP configurations on top of the Public IP with subnet IP configuration.') +param additionalPublicIpConfigurations array = [] + +@description('Optional. Specifies the properties of the Public IP to create and be used by the Firewall, if no existing public IP was provided.') +param publicIPAddressObject object = { + name: '${name}-pip' +} + +@description('Optional. The Management Public IP resource ID to associate to the AzureFirewallManagementSubnet. If empty, then the Management Public IP that is created as part of this module will be applied to the AzureFirewallManagementSubnet.') +param managementIPResourceID string = '' + +@description('Optional. Specifies the properties of the Management Public IP to create and be used by Azure Firewall. If it\'s not provided and managementIPResourceID is empty, a \'-mip\' suffix will be appended to the Firewall\'s name.') +param managementIPAddressObject object = {} + +@description('Optional. Collection of application rule collections used by Azure Firewall.') +param applicationRuleCollections array = [] + +@description('Optional. Collection of network rule collections used by Azure Firewall.') +param networkRuleCollections array = [] + +@description('Optional. Collection of NAT rule collections used by Azure Firewall.') +param natRuleCollections array = [] + +@description('Optional. Resource ID of the Firewall Policy that should be attached.') +param firewallPolicyId string = '' + +@description('Conditional. IP addresses associated with AzureFirewall. Required if `virtualHubId` is supplied.') +param hubIPAddresses object = {} + +@description('Conditional. The virtualHub resource ID to which the firewall belongs. Required if `virtualNetworkId` is empty.') +param virtualHubId string = '' + +@allowed([ + 'Alert' + 'Deny' + 'Off' +]) +@description('Optional. The operation mode for Threat Intel.') +param threatIntelMode string = 'Deny' + +@description('Optional. Zone numbers e.g. 1,2,3.') +param zones array = [ + '1' + '2' + '3' +] + +@description('Optional. The diagnostic settings of the service.') +param diagnosticSettings diagnosticSettingType + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. The lock settings of the service.') +param lock lockType + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +@description('Optional. Tags of the Azure Firewall resource.') +param tags object? + +@description('Optional. Enable/Disable usage telemetry for module.') +param enableTelemetry bool = true + +var azureSkuName = empty(virtualNetworkId) ? 'AZFW_Hub' : 'AZFW_VNet' +var requiresManagementIp = azureSkuTier == 'Basic' ? true : false +var isCreateDefaultManagementIP = empty(managementIPResourceID) && requiresManagementIp + +// ---------------------------------------------------------------------------- +// Prep ipConfigurations object AzureFirewallSubnet for different uses cases: +// 1. Use existing Public IP +// 2. Use new Public IP created in this module +// 3. Do not use a Public IP if publicIPAddressObject is empty + +var additionalPublicIpConfigurationsVar = [for ipConfiguration in additionalPublicIpConfigurations: { + name: ipConfiguration.name + properties: { + publicIPAddress: contains(ipConfiguration, 'publicIPAddressResourceId') ? { + id: ipConfiguration.publicIPAddressResourceId + } : null + } +}] +var ipConfigurations = concat([ + { + name: !empty(publicIPResourceID) ? last(split(publicIPResourceID, '/')) : publicIPAddress.outputs.name + properties: union({ + subnet: { + id: '${virtualNetworkId}/subnets/AzureFirewallSubnet' // The subnet name must be AzureFirewallSubnet + } + }, (!empty(publicIPResourceID) || !empty(publicIPAddressObject)) ? { + //Use existing Public IP, new Public IP created in this module, or none if neither + publicIPAddress: { + id: !empty(publicIPResourceID) ? publicIPResourceID : publicIPAddress.outputs.resourceId + } + } : {}) + } + ], additionalPublicIpConfigurationsVar) + +// ---------------------------------------------------------------------------- +// Prep managementIPConfiguration object for different uses cases: +// 1. Use existing Management Public IP +// 2. Use new Management Public IP created in this module + +var managementIPConfiguration = { + name: !empty(managementIPResourceID) ? last(split(managementIPResourceID, '/')) : managementIPAddress.outputs.name + properties: union({ + subnet: { + id: '${virtualNetworkId}/subnets/AzureFirewallManagementSubnet' // The subnet name must be AzureFirewallManagementSubnet for a 'Basic' SKU tier firewall + } + }, (!empty(publicIPResourceID) || !empty(managementIPAddressObject)) ? { + // Use existing Management Public IP, new Management Public IP created in this module, or none if neither + publicIPAddress: { + id: !empty(managementIPResourceID) ? managementIPResourceID : managementIPAddress.outputs.resourceId + } + } : {}) +} + +// ---------------------------------------------------------------------------- +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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.network-azurefirewall.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } + } + } + } +} + +module publicIPAddress 'br/public:avm/res/network/public-ip-address:0.2.1' = if (empty(publicIPResourceID) && azureSkuName == 'AZFW_VNet') { + name: '${uniqueString(deployment().name, location)}-Firewall-PIP' + params: { + name: publicIPAddressObject.name + publicIpPrefixResourceId: contains(publicIPAddressObject, 'publicIPPrefixResourceId') ? (!(empty(publicIPAddressObject.publicIPPrefixResourceId)) ? publicIPAddressObject.publicIPPrefixResourceId : '') : '' + publicIPAllocationMethod: contains(publicIPAddressObject, 'publicIPAllocationMethod') ? (!(empty(publicIPAddressObject.publicIPAllocationMethod)) ? publicIPAddressObject.publicIPAllocationMethod : 'Static') : 'Static' + skuName: contains(publicIPAddressObject, 'skuName') ? (!(empty(publicIPAddressObject.skuName)) ? publicIPAddressObject.skuName : 'Standard') : 'Standard' + skuTier: contains(publicIPAddressObject, 'skuTier') ? (!(empty(publicIPAddressObject.skuTier)) ? publicIPAddressObject.skuTier : 'Regional') : 'Regional' + roleAssignments: contains(publicIPAddressObject, 'roleAssignments') ? (!empty(publicIPAddressObject.roleAssignments) ? publicIPAddressObject.roleAssignments : []) : [] + diagnosticSettings: publicIPAddressObject.?diagnosticSettings + location: location + lock: lock + tags: publicIPAddressObject.?tags ?? tags + zones: zones + enableTelemetry: publicIPAddressObject.?enableTelemetry ?? enableTelemetry + } +} + +// create a Management Public IP address if one is not provided and the flag is true +module managementIPAddress 'br/public:avm/res/network/public-ip-address:0.2.1' = if (isCreateDefaultManagementIP && azureSkuName == 'AZFW_VNet') { + name: '${uniqueString(deployment().name, location)}-Firewall-MIP' + params: { + name: contains(managementIPAddressObject, 'name') ? (!(empty(managementIPAddressObject.name)) ? managementIPAddressObject.name : '${name}-mip') : '${name}-mip' + publicIpPrefixResourceId: contains(managementIPAddressObject, 'managementIPPrefixResourceId') ? (!(empty(managementIPAddressObject.publicIPPrefixResourceId)) ? managementIPAddressObject.publicIPPrefixResourceId : '') : '' + publicIPAllocationMethod: contains(managementIPAddressObject, 'managementIPAllocationMethod') ? (!(empty(managementIPAddressObject.publicIPAllocationMethod)) ? managementIPAddressObject.publicIPAllocationMethod : 'Static') : 'Static' + skuName: contains(managementIPAddressObject, 'skuName') ? (!(empty(managementIPAddressObject.skuName)) ? managementIPAddressObject.skuName : 'Standard') : 'Standard' + skuTier: contains(managementIPAddressObject, 'skuTier') ? (!(empty(managementIPAddressObject.skuTier)) ? managementIPAddressObject.skuTier : 'Regional') : 'Regional' + roleAssignments: contains(managementIPAddressObject, 'roleAssignments') ? (!empty(managementIPAddressObject.roleAssignments) ? managementIPAddressObject.roleAssignments : []) : [] + diagnosticSettings: managementIPAddressObject.?diagnosticSettings + location: location + tags: managementIPAddressObject.?tags ?? tags + zones: zones + enableTelemetry: managementIPAddressObject.?enableTelemetry ?? enableTelemetry + } +} + +resource azureFirewall 'Microsoft.Network/azureFirewalls@2023-04-01' = { + name: name + location: location + zones: length(zones) == 0 ? null : zones + tags: tags + properties: azureSkuName == 'AZFW_VNet' ? { + threatIntelMode: threatIntelMode + firewallPolicy: !empty(firewallPolicyId) ? { + id: firewallPolicyId + } : null + ipConfigurations: ipConfigurations + managementIpConfiguration: requiresManagementIp ? managementIPConfiguration : null + sku: { + name: azureSkuName + tier: azureSkuTier + } + applicationRuleCollections: applicationRuleCollections + natRuleCollections: natRuleCollections + networkRuleCollections: networkRuleCollections + } : { + firewallPolicy: !empty(firewallPolicyId) ? { + id: firewallPolicyId + } : null + sku: { + name: azureSkuName + tier: azureSkuTier + } + hubIPAddresses: !empty(hubIPAddresses) ? hubIPAddresses : null + virtualHub: !empty(virtualHubId) ? { + id: virtualHubId + } : null + } +} + +resource azureFirewall_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: azureFirewall +} + +resource azureFirewall_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + }] + logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + }] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: azureFirewall +}] + +resource azureFirewall_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(azureFirewall.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: azureFirewall +}] + +@description('The resource ID of the Azure Firewall.') +output resourceId string = azureFirewall.id + +@description('The name of the Azure Firewall.') +output name string = azureFirewall.name + +@description('The resource group the Azure firewall was deployed into.') +output resourceGroupName string = resourceGroup().name + +@description('The private IP of the Azure firewall.') +output privateIp string = contains(azureFirewall.properties, 'ipConfigurations') ? azureFirewall.properties.ipConfigurations[0].properties.privateIPAddress : '' + +@description('The Public IP configuration object for the Azure Firewall Subnet.') +output ipConfAzureFirewallSubnet object = contains(azureFirewall.properties, 'ipConfigurations') ? azureFirewall.properties.ipConfigurations[0] : {} + +@description('List of Application Rule Collections.') +output applicationRuleCollections array = applicationRuleCollections + +@description('List of Network Rule Collections.') +output networkRuleCollections array = networkRuleCollections + +@description('Collection of NAT rule collections used by Azure Firewall.') +output natRuleCollections array = natRuleCollections + +@description('The location the resource was deployed into.') +output location string = azureFirewall.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('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/network/azure-firewall/main.json b/avm/res/network/azure-firewall/main.json new file mode 100644 index 0000000000..0d3a43ef89 --- /dev/null +++ b/avm/res/network/azure-firewall/main.json @@ -0,0 +1,1784 @@ +{ + "$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": "1020924055893877667" + }, + "name": "Azure Firewalls", + "description": "This module deploys an Azure Firewall.", + "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": { + "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 + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Azure Firewall." + } + }, + "azureSkuTier": { + "type": "string", + "defaultValue": "Standard", + "allowedValues": [ + "Basic", + "Standard", + "Premium" + ], + "metadata": { + "description": "Optional. Tier of an Azure Firewall." + } + }, + "virtualNetworkId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Conditional. Shared services Virtual Network resource ID. The virtual network ID containing AzureFirewallSubnet. If a Public IP is not provided, then the Public IP that is created as part of this module will be applied with the subnet provided in this variable. Required if `virtualHubId` is empty." + } + }, + "publicIPResourceID": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The Public IP resource ID to associate to the AzureFirewallSubnet. If empty, then the Public IP that is created as part of this module will be applied to the AzureFirewallSubnet." + } + }, + "additionalPublicIpConfigurations": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. This is to add any additional Public IP configurations on top of the Public IP with subnet IP configuration." + } + }, + "publicIPAddressObject": { + "type": "object", + "defaultValue": { + "name": "[format('{0}-pip', parameters('name'))]" + }, + "metadata": { + "description": "Optional. Specifies the properties of the Public IP to create and be used by the Firewall, if no existing public IP was provided." + } + }, + "managementIPResourceID": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The Management Public IP resource ID to associate to the AzureFirewallManagementSubnet. If empty, then the Management Public IP that is created as part of this module will be applied to the AzureFirewallManagementSubnet." + } + }, + "managementIPAddressObject": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Specifies the properties of the Management Public IP to create and be used by Azure Firewall. If it's not provided and managementIPResourceID is empty, a '-mip' suffix will be appended to the Firewall's name." + } + }, + "applicationRuleCollections": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Collection of application rule collections used by Azure Firewall." + } + }, + "networkRuleCollections": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Collection of network rule collections used by Azure Firewall." + } + }, + "natRuleCollections": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Collection of NAT rule collections used by Azure Firewall." + } + }, + "firewallPolicyId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the Firewall Policy that should be attached." + } + }, + "hubIPAddresses": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Conditional. IP addresses associated with AzureFirewall. Required if `virtualHubId` is supplied." + } + }, + "virtualHubId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Conditional. The virtualHub resource ID to which the firewall belongs. Required if `virtualNetworkId` is empty." + } + }, + "threatIntelMode": { + "type": "string", + "defaultValue": "Deny", + "allowedValues": [ + "Alert", + "Deny", + "Off" + ], + "metadata": { + "description": "Optional. The operation mode for Threat Intel." + } + }, + "zones": { + "type": "array", + "defaultValue": [ + "1", + "2", + "3" + ], + "metadata": { + "description": "Optional. Zone numbers e.g. 1,2,3." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + }, + "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 of the Azure Firewall resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "copy": [ + { + "name": "additionalPublicIpConfigurationsVar", + "count": "[length(parameters('additionalPublicIpConfigurations'))]", + "input": { + "name": "[parameters('additionalPublicIpConfigurations')[copyIndex('additionalPublicIpConfigurationsVar')].name]", + "properties": { + "publicIPAddress": "[if(contains(parameters('additionalPublicIpConfigurations')[copyIndex('additionalPublicIpConfigurationsVar')], 'publicIPAddressResourceId'), createObject('id', parameters('additionalPublicIpConfigurations')[copyIndex('additionalPublicIpConfigurationsVar')].publicIPAddressResourceId), null())]" + } + } + } + ], + "azureSkuName": "[if(empty(parameters('virtualNetworkId')), 'AZFW_Hub', 'AZFW_VNet')]", + "requiresManagementIp": "[if(equals(parameters('azureSkuTier'), 'Basic'), true(), false())]", + "isCreateDefaultManagementIP": "[and(empty(parameters('managementIPResourceID')), variables('requiresManagementIp'))]", + "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 (Preview)": "[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": "2023-07-01", + "name": "[format('46d3xbcp.res.network-azurefirewall.{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" + } + } + } + } + }, + "azureFirewall": { + "type": "Microsoft.Network/azureFirewalls", + "apiVersion": "2023-04-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "zones": "[if(equals(length(parameters('zones')), 0), null(), parameters('zones'))]", + "tags": "[parameters('tags')]", + "properties": "[if(equals(variables('azureSkuName'), 'AZFW_VNet'), createObject('threatIntelMode', parameters('threatIntelMode'), 'firewallPolicy', if(not(empty(parameters('firewallPolicyId'))), createObject('id', parameters('firewallPolicyId')), null()), 'ipConfigurations', concat(createArray(createObject('name', if(not(empty(parameters('publicIPResourceID'))), last(split(parameters('publicIPResourceID'), '/')), reference('publicIPAddress').outputs.name.value), 'properties', union(createObject('subnet', createObject('id', format('{0}/subnets/AzureFirewallSubnet', parameters('virtualNetworkId')))), if(or(not(empty(parameters('publicIPResourceID'))), not(empty(parameters('publicIPAddressObject')))), createObject('publicIPAddress', createObject('id', if(not(empty(parameters('publicIPResourceID'))), parameters('publicIPResourceID'), reference('publicIPAddress').outputs.resourceId.value))), createObject())))), variables('additionalPublicIpConfigurationsVar')), 'managementIpConfiguration', if(variables('requiresManagementIp'), createObject('name', if(not(empty(parameters('managementIPResourceID'))), last(split(parameters('managementIPResourceID'), '/')), reference('managementIPAddress').outputs.name.value), 'properties', union(createObject('subnet', createObject('id', format('{0}/subnets/AzureFirewallManagementSubnet', parameters('virtualNetworkId')))), if(or(not(empty(parameters('publicIPResourceID'))), not(empty(parameters('managementIPAddressObject')))), createObject('publicIPAddress', createObject('id', if(not(empty(parameters('managementIPResourceID'))), parameters('managementIPResourceID'), reference('managementIPAddress').outputs.resourceId.value))), createObject()))), null()), 'sku', createObject('name', variables('azureSkuName'), 'tier', parameters('azureSkuTier')), 'applicationRuleCollections', parameters('applicationRuleCollections'), 'natRuleCollections', parameters('natRuleCollections'), 'networkRuleCollections', parameters('networkRuleCollections')), createObject('firewallPolicy', if(not(empty(parameters('firewallPolicyId'))), createObject('id', parameters('firewallPolicyId')), null()), 'sku', createObject('name', variables('azureSkuName'), 'tier', parameters('azureSkuTier')), 'hubIPAddresses', if(not(empty(parameters('hubIPAddresses'))), parameters('hubIPAddresses'), null()), 'virtualHub', if(not(empty(parameters('virtualHubId'))), createObject('id', parameters('virtualHubId')), null())))]", + "dependsOn": [ + "managementIPAddress", + "publicIPAddress" + ] + }, + "azureFirewall_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/azureFirewalls/{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": [ + "azureFirewall" + ] + }, + "azureFirewall_diagnosticSettings": { + "copy": { + "name": "azureFirewall_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Network/azureFirewalls/{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": [ + "azureFirewall" + ] + }, + "azureFirewall_roleAssignments": { + "copy": { + "name": "azureFirewall_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/azureFirewalls/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Network/azureFirewalls', 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": [ + "azureFirewall" + ] + }, + "publicIPAddress": { + "condition": "[and(empty(parameters('publicIPResourceID')), equals(variables('azureSkuName'), 'AZFW_VNet'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Firewall-PIP', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('publicIPAddressObject').name]" + }, + "publicIpPrefixResourceId": "[if(contains(parameters('publicIPAddressObject'), 'publicIPPrefixResourceId'), if(not(empty(parameters('publicIPAddressObject').publicIPPrefixResourceId)), createObject('value', parameters('publicIPAddressObject').publicIPPrefixResourceId), createObject('value', '')), createObject('value', ''))]", + "publicIPAllocationMethod": "[if(contains(parameters('publicIPAddressObject'), 'publicIPAllocationMethod'), if(not(empty(parameters('publicIPAddressObject').publicIPAllocationMethod)), createObject('value', parameters('publicIPAddressObject').publicIPAllocationMethod), createObject('value', 'Static')), createObject('value', 'Static'))]", + "skuName": "[if(contains(parameters('publicIPAddressObject'), 'skuName'), if(not(empty(parameters('publicIPAddressObject').skuName)), createObject('value', parameters('publicIPAddressObject').skuName), createObject('value', 'Standard')), createObject('value', 'Standard'))]", + "skuTier": "[if(contains(parameters('publicIPAddressObject'), 'skuTier'), if(not(empty(parameters('publicIPAddressObject').skuTier)), createObject('value', parameters('publicIPAddressObject').skuTier), createObject('value', 'Regional')), createObject('value', 'Regional'))]", + "roleAssignments": "[if(contains(parameters('publicIPAddressObject'), 'roleAssignments'), if(not(empty(parameters('publicIPAddressObject').roleAssignments)), createObject('value', parameters('publicIPAddressObject').roleAssignments), createObject('value', createArray())), createObject('value', createArray()))]", + "diagnosticSettings": { + "value": "[tryGet(parameters('publicIPAddressObject'), 'diagnosticSettings')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "lock": { + "value": "[parameters('lock')]" + }, + "tags": { + "value": "[coalesce(tryGet(parameters('publicIPAddressObject'), 'tags'), parameters('tags'))]" + }, + "zones": { + "value": "[parameters('zones')]" + }, + "enableTelemetry": { + "value": "[coalesce(tryGet(parameters('publicIPAddressObject'), '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": "3488076626994379707" + }, + "name": "Public IP Addresses", + "description": "This module deploys a Public IP Address.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "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": { + "domainNameLabel": { + "type": "string", + "metadata": { + "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." + } + }, + "domainNameLabelScope": { + "type": "string", + "allowedValues": [ + "", + "NoReuse", + "ResourceGroupReuse", + "SubscriptionReuse", + "TenantReuse" + ], + "metadata": { + "description": "Required. The domain name label scope. If a domain name label and a domain name label scope are specified, an A DNS record is created for the public IP in the Microsoft Azure DNS system with a hashed value includes in FQDN." + } + }, + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Fully Qualified Domain Name of the A DNS record associated with the public IP. This is the concatenation of the domainNameLabel and the regionalized DNS zone." + } + }, + "reverseFqdn": { + "type": "string", + "nullable": true, + "metadata": { + "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." + } + } + } + }, + "ddosSettingsType": { + "type": "object", + "properties": { + "ddosProtectionPlan": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + }, + "metadata": { + "description": "Required. The DDoS protection plan ID associated with the public IP address." + } + }, + "protectionMode": { + "type": "string", + "allowedValues": [ + "Enabled" + ], + "metadata": { + "description": "Required. The DDoS protection policy customizations." + } + } + } + }, + "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." + } + }, + "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." + } + } + } + }, + "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 + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Public IP Address." + } + }, + "publicIpPrefixResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix." + } + }, + "publicIPAllocationMethod": { + "type": "string", + "defaultValue": "Static", + "allowedValues": [ + "Dynamic", + "Static" + ], + "metadata": { + "description": "Optional. The public IP address allocation method." + } + }, + "zones": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. A list of availability zones denoting the IP allocated for the resource needs to come from." + } + }, + "publicIPAddressVersion": { + "type": "string", + "defaultValue": "IPv4", + "allowedValues": [ + "IPv4", + "IPv6" + ], + "metadata": { + "description": "Optional. IP address version." + } + }, + "dnsSettings": { + "$ref": "#/definitions/dnsSettingsType", + "nullable": true, + "metadata": { + "description": "Optional. The DNS settings of the public IP address." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "skuName": { + "type": "string", + "defaultValue": "Standard", + "allowedValues": [ + "Basic", + "Standard" + ], + "metadata": { + "description": "Optional. Name of a public IP address SKU." + } + }, + "skuTier": { + "type": "string", + "defaultValue": "Regional", + "allowedValues": [ + "Global", + "Regional" + ], + "metadata": { + "description": "Optional. Tier of a public IP address SKU." + } + }, + "ddosSettings": { + "$ref": "#/definitions/ddosSettingsType", + "nullable": true, + "metadata": { + "description": "Optional. The DDoS protection plan configuration associated with the public IP address." + } + }, + "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." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "idleTimeoutInMinutes": { + "type": "int", + "defaultValue": 4, + "metadata": { + "description": "Optional. The idle timeout of the public IP address." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + } + }, + "variables": { + "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": "2023-07-01", + "name": "[format('46d3xbcp.res.network-publicipaddress.{0}.{1}', replace('0.2.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" + } + } + } + } + }, + "publicIpAddress": { + "type": "Microsoft.Network/publicIPAddresses", + "apiVersion": "2023-04-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "sku": { + "name": "[parameters('skuName')]", + "tier": "[parameters('skuTier')]" + }, + "zones": "[parameters('zones')]", + "properties": { + "ddosSettings": "[parameters('ddosSettings')]", + "dnsSettings": "[parameters('dnsSettings')]", + "publicIPAddressVersion": "[parameters('publicIPAddressVersion')]", + "publicIPAllocationMethod": "[parameters('publicIPAllocationMethod')]", + "publicIPPrefix": "[if(not(empty(parameters('publicIpPrefixResourceId'))), createObject('id', parameters('publicIpPrefixResourceId')), null())]", + "idleTimeoutInMinutes": "[parameters('idleTimeoutInMinutes')]", + "ipTags": [] + } + }, + "publicIpAddress_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/publicIPAddresses/{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": [ + "publicIpAddress" + ] + }, + "publicIpAddress_roleAssignments": { + "copy": { + "name": "publicIpAddress_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/publicIPAddresses/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Network/publicIPAddresses', 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": [ + "publicIpAddress" + ] + }, + "publicIpAddress_diagnosticSettings": { + "copy": { + "name": "publicIpAddress_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Network/publicIPAddresses/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'name'), format('{0}-diagnosticSettings', parameters('name')))]", + "properties": { + "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')]", + "metrics": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics', 'timeGrain', null(), 'enabled', true())))]", + "logs": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs', 'enabled', true())))]", + "marketplacePartnerId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'marketplacePartnerResourceId')]", + "logAnalyticsDestinationType": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logAnalyticsDestinationType')]" + }, + "dependsOn": [ + "publicIpAddress" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the public IP address was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the public IP address." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the public IP address." + }, + "value": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('name'))]" + }, + "ipAddress": { + "type": "string", + "metadata": { + "description": "The public IP address of the public IP address resource." + }, + "value": "[if(contains(reference('publicIpAddress'), 'ipAddress'), reference('publicIpAddress').ipAddress, '')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('publicIpAddress', '2023-04-01', 'full').location]" + } + } + } + } + }, + "managementIPAddress": { + "condition": "[and(variables('isCreateDefaultManagementIP'), equals(variables('azureSkuName'), 'AZFW_VNet'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Firewall-MIP', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": "[if(contains(parameters('managementIPAddressObject'), 'name'), if(not(empty(parameters('managementIPAddressObject').name)), createObject('value', parameters('managementIPAddressObject').name), createObject('value', format('{0}-mip', parameters('name')))), createObject('value', format('{0}-mip', parameters('name'))))]", + "publicIpPrefixResourceId": "[if(contains(parameters('managementIPAddressObject'), 'managementIPPrefixResourceId'), if(not(empty(parameters('managementIPAddressObject').publicIPPrefixResourceId)), createObject('value', parameters('managementIPAddressObject').publicIPPrefixResourceId), createObject('value', '')), createObject('value', ''))]", + "publicIPAllocationMethod": "[if(contains(parameters('managementIPAddressObject'), 'managementIPAllocationMethod'), if(not(empty(parameters('managementIPAddressObject').publicIPAllocationMethod)), createObject('value', parameters('managementIPAddressObject').publicIPAllocationMethod), createObject('value', 'Static')), createObject('value', 'Static'))]", + "skuName": "[if(contains(parameters('managementIPAddressObject'), 'skuName'), if(not(empty(parameters('managementIPAddressObject').skuName)), createObject('value', parameters('managementIPAddressObject').skuName), createObject('value', 'Standard')), createObject('value', 'Standard'))]", + "skuTier": "[if(contains(parameters('managementIPAddressObject'), 'skuTier'), if(not(empty(parameters('managementIPAddressObject').skuTier)), createObject('value', parameters('managementIPAddressObject').skuTier), createObject('value', 'Regional')), createObject('value', 'Regional'))]", + "roleAssignments": "[if(contains(parameters('managementIPAddressObject'), 'roleAssignments'), if(not(empty(parameters('managementIPAddressObject').roleAssignments)), createObject('value', parameters('managementIPAddressObject').roleAssignments), createObject('value', createArray())), createObject('value', createArray()))]", + "diagnosticSettings": { + "value": "[tryGet(parameters('managementIPAddressObject'), 'diagnosticSettings')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "tags": { + "value": "[coalesce(tryGet(parameters('managementIPAddressObject'), 'tags'), parameters('tags'))]" + }, + "zones": { + "value": "[parameters('zones')]" + }, + "enableTelemetry": { + "value": "[coalesce(tryGet(parameters('managementIPAddressObject'), '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": "3488076626994379707" + }, + "name": "Public IP Addresses", + "description": "This module deploys a Public IP Address.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "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": { + "domainNameLabel": { + "type": "string", + "metadata": { + "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." + } + }, + "domainNameLabelScope": { + "type": "string", + "allowedValues": [ + "", + "NoReuse", + "ResourceGroupReuse", + "SubscriptionReuse", + "TenantReuse" + ], + "metadata": { + "description": "Required. The domain name label scope. If a domain name label and a domain name label scope are specified, an A DNS record is created for the public IP in the Microsoft Azure DNS system with a hashed value includes in FQDN." + } + }, + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Fully Qualified Domain Name of the A DNS record associated with the public IP. This is the concatenation of the domainNameLabel and the regionalized DNS zone." + } + }, + "reverseFqdn": { + "type": "string", + "nullable": true, + "metadata": { + "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." + } + } + } + }, + "ddosSettingsType": { + "type": "object", + "properties": { + "ddosProtectionPlan": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + }, + "metadata": { + "description": "Required. The DDoS protection plan ID associated with the public IP address." + } + }, + "protectionMode": { + "type": "string", + "allowedValues": [ + "Enabled" + ], + "metadata": { + "description": "Required. The DDoS protection policy customizations." + } + } + } + }, + "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." + } + }, + "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." + } + } + } + }, + "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 + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Public IP Address." + } + }, + "publicIpPrefixResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix." + } + }, + "publicIPAllocationMethod": { + "type": "string", + "defaultValue": "Static", + "allowedValues": [ + "Dynamic", + "Static" + ], + "metadata": { + "description": "Optional. The public IP address allocation method." + } + }, + "zones": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. A list of availability zones denoting the IP allocated for the resource needs to come from." + } + }, + "publicIPAddressVersion": { + "type": "string", + "defaultValue": "IPv4", + "allowedValues": [ + "IPv4", + "IPv6" + ], + "metadata": { + "description": "Optional. IP address version." + } + }, + "dnsSettings": { + "$ref": "#/definitions/dnsSettingsType", + "nullable": true, + "metadata": { + "description": "Optional. The DNS settings of the public IP address." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "skuName": { + "type": "string", + "defaultValue": "Standard", + "allowedValues": [ + "Basic", + "Standard" + ], + "metadata": { + "description": "Optional. Name of a public IP address SKU." + } + }, + "skuTier": { + "type": "string", + "defaultValue": "Regional", + "allowedValues": [ + "Global", + "Regional" + ], + "metadata": { + "description": "Optional. Tier of a public IP address SKU." + } + }, + "ddosSettings": { + "$ref": "#/definitions/ddosSettingsType", + "nullable": true, + "metadata": { + "description": "Optional. The DDoS protection plan configuration associated with the public IP address." + } + }, + "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." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "idleTimeoutInMinutes": { + "type": "int", + "defaultValue": 4, + "metadata": { + "description": "Optional. The idle timeout of the public IP address." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + } + }, + "variables": { + "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": "2023-07-01", + "name": "[format('46d3xbcp.res.network-publicipaddress.{0}.{1}', replace('0.2.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" + } + } + } + } + }, + "publicIpAddress": { + "type": "Microsoft.Network/publicIPAddresses", + "apiVersion": "2023-04-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "sku": { + "name": "[parameters('skuName')]", + "tier": "[parameters('skuTier')]" + }, + "zones": "[parameters('zones')]", + "properties": { + "ddosSettings": "[parameters('ddosSettings')]", + "dnsSettings": "[parameters('dnsSettings')]", + "publicIPAddressVersion": "[parameters('publicIPAddressVersion')]", + "publicIPAllocationMethod": "[parameters('publicIPAllocationMethod')]", + "publicIPPrefix": "[if(not(empty(parameters('publicIpPrefixResourceId'))), createObject('id', parameters('publicIpPrefixResourceId')), null())]", + "idleTimeoutInMinutes": "[parameters('idleTimeoutInMinutes')]", + "ipTags": [] + } + }, + "publicIpAddress_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/publicIPAddresses/{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": [ + "publicIpAddress" + ] + }, + "publicIpAddress_roleAssignments": { + "copy": { + "name": "publicIpAddress_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/publicIPAddresses/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Network/publicIPAddresses', 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": [ + "publicIpAddress" + ] + }, + "publicIpAddress_diagnosticSettings": { + "copy": { + "name": "publicIpAddress_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Network/publicIPAddresses/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'name'), format('{0}-diagnosticSettings', parameters('name')))]", + "properties": { + "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')]", + "metrics": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics', 'timeGrain', null(), 'enabled', true())))]", + "logs": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs', 'enabled', true())))]", + "marketplacePartnerId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'marketplacePartnerResourceId')]", + "logAnalyticsDestinationType": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logAnalyticsDestinationType')]" + }, + "dependsOn": [ + "publicIpAddress" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the public IP address was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the public IP address." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the public IP address." + }, + "value": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('name'))]" + }, + "ipAddress": { + "type": "string", + "metadata": { + "description": "The public IP address of the public IP address resource." + }, + "value": "[if(contains(reference('publicIpAddress'), 'ipAddress'), reference('publicIpAddress').ipAddress, '')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('publicIpAddress', '2023-04-01', 'full').location]" + } + } + } + } + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Azure Firewall." + }, + "value": "[resourceId('Microsoft.Network/azureFirewalls', parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the Azure Firewall." + }, + "value": "[parameters('name')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the Azure firewall was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "privateIp": { + "type": "string", + "metadata": { + "description": "The private IP of the Azure firewall." + }, + "value": "[if(contains(reference('azureFirewall'), 'ipConfigurations'), reference('azureFirewall').ipConfigurations[0].properties.privateIPAddress, '')]" + }, + "ipConfAzureFirewallSubnet": { + "type": "object", + "metadata": { + "description": "The Public IP configuration object for the Azure Firewall Subnet." + }, + "value": "[if(contains(reference('azureFirewall'), 'ipConfigurations'), reference('azureFirewall').ipConfigurations[0], createObject())]" + }, + "applicationRuleCollections": { + "type": "array", + "metadata": { + "description": "List of Application Rule Collections." + }, + "value": "[parameters('applicationRuleCollections')]" + }, + "networkRuleCollections": { + "type": "array", + "metadata": { + "description": "List of Network Rule Collections." + }, + "value": "[parameters('networkRuleCollections')]" + }, + "natRuleCollections": { + "type": "array", + "metadata": { + "description": "Collection of NAT rule collections used by Azure Firewall." + }, + "value": "[parameters('natRuleCollections')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('azureFirewall', '2023-04-01', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/network/azure-firewall/tests/e2e/addpip/dependencies.bicep b/avm/res/network/azure-firewall/tests/e2e/addpip/dependencies.bicep new file mode 100644 index 0000000000..cf2cb1747a --- /dev/null +++ b/avm/res/network/azure-firewall/tests/e2e/addpip/dependencies.bicep @@ -0,0 +1,70 @@ +@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 + +@description('Required. The name of the Public IP to create.') +param publicIPName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +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: 'AzureFirewallSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 20, 0) + } + } + { + name: 'AzureFirewallManagementSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 20, 1) + } + } + ] + } +} + +resource publicIP 'Microsoft.Network/publicIPAddresses@2023-04-01' = { + name: publicIPName + location: location + sku: { + name: 'Standard' + tier: 'Regional' + } + properties: { + publicIPAllocationMethod: 'Static' + } + zones: [ + '1' + '2' + '3' + ] +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The resource ID of the created Virtual Network.') +output virtualNetworkResourceId string = virtualNetwork.id + +@description('The resource ID of the created Public IP.') +output publicIPResourceId string = publicIP.id + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/network/azure-firewall/tests/e2e/addpip/main.test.bicep b/avm/res/network/azure-firewall/tests/e2e/addpip/main.test.bicep new file mode 100644 index 0000000000..4a27824896 --- /dev/null +++ b/avm/res/network/azure-firewall/tests/e2e/addpip/main.test.bicep @@ -0,0 +1,75 @@ +targetScope = 'subscription' + +metadata name = 'Add-PIP' +metadata description = 'This instance deploys the module and attaches an existing public IP address.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-network.azurefirewalls-${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 = 'nafaddpip' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + location: resourceLocation + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + publicIPName: 'dep-${namePrefix}-pip-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + virtualNetworkId: nestedDependencies.outputs.virtualNetworkResourceId + additionalPublicIpConfigurations: [ + { + name: 'ipConfig01' + publicIPAddressResourceId: nestedDependencies.outputs.publicIPResourceId + } + ] + azureSkuTier: 'Basic' + managementIPAddressObject: { + publicIPAllocationMethod: 'Static' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + } + } +}] diff --git a/avm/res/network/azure-firewall/tests/e2e/custompip/dependencies.bicep b/avm/res/network/azure-firewall/tests/e2e/custompip/dependencies.bicep new file mode 100644 index 0000000000..5d14b0b91c --- /dev/null +++ b/avm/res/network/azure-firewall/tests/e2e/custompip/dependencies.bicep @@ -0,0 +1,41 @@ +@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 + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +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: 'AzureFirewallSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + } + } + ] + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The resource ID of the created Virtual Network.') +output virtualNetworkResourceId string = virtualNetwork.id + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/network/azure-firewall/tests/e2e/custompip/main.test.bicep b/avm/res/network/azure-firewall/tests/e2e/custompip/main.test.bicep new file mode 100644 index 0000000000..e201b2d21f --- /dev/null +++ b/avm/res/network/azure-firewall/tests/e2e/custompip/main.test.bicep @@ -0,0 +1,99 @@ +targetScope = 'subscription' + +metadata name = 'Custom-PIP' +metadata description = 'This instance deploys the module and will create a public IP address.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-network.azurefirewalls-${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 = 'nafcstpip' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + location: resourceLocation + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-diagnosticDependencies' + params: { + storageAccountName: 'dep${namePrefix}diasa${serviceShort}03' + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}01' + eventHubNamespaceName: 'dep-${namePrefix}-evhns-${serviceShort}01' + 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: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + virtualNetworkId: nestedDependencies.outputs.virtualNetworkResourceId + publicIPAddressObject: { + name: 'new-${namePrefix}-pip-${serviceShort}' + publicIPAllocationMethod: 'Static' + publicIPPrefixResourceId: '' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + skuName: 'Standard' + skuTier: 'Regional' + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + } + } +}] diff --git a/avm/res/network/azure-firewall/tests/e2e/defaults/dependencies.bicep b/avm/res/network/azure-firewall/tests/e2e/defaults/dependencies.bicep new file mode 100644 index 0000000000..4d1cd2e6aa --- /dev/null +++ b/avm/res/network/azure-firewall/tests/e2e/defaults/dependencies.bicep @@ -0,0 +1,29 @@ +@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@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'AzureFirewallSubnet' + 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/azure-firewall/tests/e2e/defaults/main.test.bicep b/avm/res/network/azure-firewall/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..8ec00541a0 --- /dev/null +++ b/avm/res/network/azure-firewall/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,56 @@ +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}-network.azurefirewalls-${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 = 'nafmin' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +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' + virtualNetworkId: nestedDependencies.outputs.virtualNetworkResourceId + location: resourceLocation + } +}] diff --git a/avm/res/network/azure-firewall/tests/e2e/hubcommon/dependencies.bicep b/avm/res/network/azure-firewall/tests/e2e/hubcommon/dependencies.bicep new file mode 100644 index 0000000000..0dc2f1d9a2 --- /dev/null +++ b/avm/res/network/azure-firewall/tests/e2e/hubcommon/dependencies.bicep @@ -0,0 +1,46 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual WAN to create.') +param virtualWanName string + +@description('Required. The name of the Virtual Hub to create.') +param virtualHubName string + +@description('Required. The name of the Firewall Policy to create.') +param firewallPolicyName string + +resource virtualWan 'Microsoft.Network/virtualWans@2023-04-01' = { + name: virtualWanName + location: location + properties: { + disableVpnEncryption: false + allowBranchToBranchTraffic: true + type: 'Standard' + } +} + +resource virtualHub 'Microsoft.Network/virtualHubs@2021-08-01' = { + name: virtualHubName + location: location + properties: { + addressPrefix: '10.1.0.0/16' + virtualWan: { + id: virtualWan.id + } + } +} + +resource policy 'Microsoft.Network/firewallPolicies@2023-04-01' = { + name: firewallPolicyName + location: location + properties: { + threatIntelMode: 'Alert' + } +} + +@description('The resource ID of the created Virtual Hub.') +output virtualHubResourceId string = virtualHub.id + +@description('The resource ID of the created Firewall Policy.') +output firewallPolicyResourceId string = policy.id diff --git a/avm/res/network/azure-firewall/tests/e2e/hubcommon/main.test.bicep b/avm/res/network/azure-firewall/tests/e2e/hubcommon/main.test.bicep new file mode 100644 index 0000000000..91f5a5b7f4 --- /dev/null +++ b/avm/res/network/azure-firewall/tests/e2e/hubcommon/main.test.bicep @@ -0,0 +1,64 @@ +targetScope = 'subscription' + +metadata name = 'Hub-commom' +metadata description = 'This instance deploys the module a vWAN in a typical hub setting.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-network.azurefirewalls-${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 = 'nafhubcom' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + location: resourceLocation + virtualWanName: 'dep-${namePrefix}-vwan-${serviceShort}' + virtualHubName: 'dep-${namePrefix}-vhub-${serviceShort}' + firewallPolicyName: 'dep-${namePrefix}-afwp-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + firewallPolicyId: nestedDependencies.outputs.firewallPolicyResourceId + virtualHubId: nestedDependencies.outputs.virtualHubResourceId + hubIPAddresses: { + publicIPs: { + count: 1 + } + } + } +}] diff --git a/avm/res/network/azure-firewall/tests/e2e/hubmin/dependencies.bicep b/avm/res/network/azure-firewall/tests/e2e/hubmin/dependencies.bicep new file mode 100644 index 0000000000..eceb77c39e --- /dev/null +++ b/avm/res/network/azure-firewall/tests/e2e/hubmin/dependencies.bicep @@ -0,0 +1,32 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual WAN to create.') +param virtualWanName string + +@description('Required. The name of the Virtual Hub to create.') +param virtualHubName string + +resource virtualWan 'Microsoft.Network/virtualWans@2023-04-01' = { + name: virtualWanName + location: location + properties: { + disableVpnEncryption: false + allowBranchToBranchTraffic: true + type: 'Standard' + } +} + +resource virtualHub 'Microsoft.Network/virtualHubs@2021-08-01' = { + name: virtualHubName + location: location + properties: { + addressPrefix: '10.1.0.0/16' + virtualWan: { + id: virtualWan.id + } + } +} + +@description('The resource ID of the created Virtual Hub.') +output virtualHubResourceId string = virtualHub.id diff --git a/avm/res/network/azure-firewall/tests/e2e/hubmin/main.test.bicep b/avm/res/network/azure-firewall/tests/e2e/hubmin/main.test.bicep new file mode 100644 index 0000000000..25efd33efb --- /dev/null +++ b/avm/res/network/azure-firewall/tests/e2e/hubmin/main.test.bicep @@ -0,0 +1,62 @@ +targetScope = 'subscription' + +metadata name = 'Hub-min' +metadata description = 'This instance deploys the module a vWAN minimum hub setting.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-network.azurefirewalls-${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 = 'nafhubmin' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + virtualWanName: 'dep-${namePrefix}-vwan-${serviceShort}' + virtualHubName: 'dep-${namePrefix}-vhub-${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: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + virtualHubId: nestedDependencies.outputs.virtualHubResourceId + hubIPAddresses: { + publicIPs: { + count: 1 + } + } + } +}] diff --git a/avm/res/network/azure-firewall/tests/e2e/max/dependencies.bicep b/avm/res/network/azure-firewall/tests/e2e/max/dependencies.bicep new file mode 100644 index 0000000000..de9bfec4ea --- /dev/null +++ b/avm/res/network/azure-firewall/tests/e2e/max/dependencies.bicep @@ -0,0 +1,64 @@ +@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 + +@description('Required. The name of the Public IP to create.') +param publicIPName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +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: 'AzureFirewallSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + } + } + ] + } +} + +resource publicIP 'Microsoft.Network/publicIPAddresses@2023-04-01' = { + name: publicIPName + location: location + sku: { + name: 'Standard' + tier: 'Regional' + } + properties: { + publicIPAllocationMethod: 'Static' + } + zones: [ + '1' + '2' + '3' + ] +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The resource ID of the created Virtual Network.') +output virtualNetworkResourceId string = virtualNetwork.id + +@description('The resource ID of the created Public IP.') +output publicIPResourceId string = publicIP.id + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/network/azure-firewall/tests/e2e/max/main.test.bicep b/avm/res/network/azure-firewall/tests/e2e/max/main.test.bicep new file mode 100644 index 0000000000..51b94e2234 --- /dev/null +++ b/avm/res/network/azure-firewall/tests/e2e/max/main.test.bicep @@ -0,0 +1,199 @@ +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}-network.azurefirewalls-${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 = 'nafmax' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + publicIPName: 'dep-${namePrefix}-pip-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: resourceLocation + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-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 + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + virtualNetworkId: nestedDependencies.outputs.virtualNetworkResourceId + applicationRuleCollections: [ + { + name: 'allow-app-rules' + properties: { + action: { + type: 'allow' + } + priority: 100 + rules: [ + { + fqdnTags: [ + 'AppServiceEnvironment' + 'WindowsUpdate' + ] + name: 'allow-ase-tags' + protocols: [ + { + port: '80' + protocolType: 'HTTP' + } + { + port: '443' + protocolType: 'HTTPS' + } + ] + sourceAddresses: [ + '*' + ] + } + { + name: 'allow-ase-management' + protocols: [ + { + port: '80' + protocolType: 'HTTP' + } + { + port: '443' + protocolType: 'HTTPS' + } + ] + sourceAddresses: [ + '*' + ] + targetFqdns: [ + 'bing.com' + ] + } + ] + } + } + ] + publicIPResourceID: nestedDependencies.outputs.publicIPResourceId + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + networkRuleCollections: [ + { + name: 'allow-network-rules' + properties: { + action: { + type: 'allow' + } + priority: 100 + rules: [ + { + destinationAddresses: [ + '*' + ] + destinationPorts: [ + '12000' + '123' + ] + name: 'allow-ntp' + protocols: [ + 'Any' + ] + sourceAddresses: [ + '*' + ] + } + ] + } + } + ] + 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' + } + ] + zones: [ + '1' + '2' + '3' + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/network/azure-firewall/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/network/azure-firewall/tests/e2e/waf-aligned/dependencies.bicep new file mode 100644 index 0000000000..de9bfec4ea --- /dev/null +++ b/avm/res/network/azure-firewall/tests/e2e/waf-aligned/dependencies.bicep @@ -0,0 +1,64 @@ +@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 + +@description('Required. The name of the Public IP to create.') +param publicIPName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +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: 'AzureFirewallSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + } + } + ] + } +} + +resource publicIP 'Microsoft.Network/publicIPAddresses@2023-04-01' = { + name: publicIPName + location: location + sku: { + name: 'Standard' + tier: 'Regional' + } + properties: { + publicIPAllocationMethod: 'Static' + } + zones: [ + '1' + '2' + '3' + ] +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The resource ID of the created Virtual Network.') +output virtualNetworkResourceId string = virtualNetwork.id + +@description('The resource ID of the created Public IP.') +output publicIPResourceId string = publicIP.id + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/network/azure-firewall/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/azure-firewall/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..524ca25f25 --- /dev/null +++ b/avm/res/network/azure-firewall/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,178 @@ +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}-network.azurefirewalls-${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 = 'nafwaf' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + publicIPName: 'dep-${namePrefix}-pip-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: resourceLocation + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-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 + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + virtualNetworkId: nestedDependencies.outputs.virtualNetworkResourceId + applicationRuleCollections: [ + { + name: 'allow-app-rules' + properties: { + action: { + type: 'allow' + } + priority: 100 + rules: [ + { + fqdnTags: [ + 'AppServiceEnvironment' + 'WindowsUpdate' + ] + name: 'allow-ase-tags' + protocols: [ + { + port: '80' + protocolType: 'HTTP' + } + { + port: '443' + protocolType: 'HTTPS' + } + ] + sourceAddresses: [ + '*' + ] + } + { + name: 'allow-ase-management' + protocols: [ + { + port: '80' + protocolType: 'HTTP' + } + { + port: '443' + protocolType: 'HTTPS' + } + ] + sourceAddresses: [ + '*' + ] + targetFqdns: [ + 'bing.com' + ] + } + ] + } + } + ] + publicIPResourceID: nestedDependencies.outputs.publicIPResourceId + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + networkRuleCollections: [ + { + name: 'allow-network-rules' + properties: { + action: { + type: 'allow' + } + priority: 100 + rules: [ + { + destinationAddresses: [ + '*' + ] + destinationPorts: [ + '12000' + '123' + ] + name: 'allow-ntp' + protocols: [ + 'Any' + ] + sourceAddresses: [ + '*' + ] + } + ] + } + } + ] + zones: [ + '1' + '2' + '3' + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/network/azure-firewall/version.json b/avm/res/network/azure-firewall/version.json new file mode 100644 index 0000000000..83083db694 --- /dev/null +++ b/avm/res/network/azure-firewall/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.1", + "pathFilters": [ + "./main.json" + ] +} \ No newline at end of file From 514157f06148066a2cf96ea7103e739eb67a1f76 Mon Sep 17 00:00:00 2001 From: Erika Gressi <56914614+eriqua@users.noreply.github.com> Date: Tue, 12 Mar 2024 16:35:58 +0000 Subject: [PATCH 10/73] fix: `virtual-machine-images/image-template`, `resource-graph/query` and `synapse/workspace` patch update to enforce publish with source (#1260) ## Description Minor parameter description update to enforce new patch version to be published with source ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.virtual-machine-images.image-template](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.virtual-machine-images.image-template.yml/badge.svg?branch=fix%2Feriqua%2Fenforce-pub-src)](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.virtual-machine-images.image-template.yml) | | [![avm.res.resource-graph.query](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.resource-graph.query.yml/badge.svg?branch=fix%2Feriqua%2Fenforce-pub-src)](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.resource-graph.query.yml) | | [![avm.res.synapse.workspace](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.synapse.workspace.yml/badge.svg?branch=fix%2Feriqua%2Fenforce-pub-src)](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.synapse.workspace.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [x] Azure Verified Module updates: - [x] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [x] I have run `Set-AVMModule` locally to generate the supporting module files. - [x] My corresponding pipelines / checks run clean and green without any errors or warnings --- avm/res/resource-graph/query/README.md | 4 ++-- avm/res/resource-graph/query/main.bicep | 2 +- avm/res/resource-graph/query/main.json | 4 ++-- avm/res/synapse/workspace/key/README.md | 4 ++-- avm/res/synapse/workspace/key/main.bicep | 2 +- avm/res/synapse/workspace/key/main.json | 4 ++-- avm/res/synapse/workspace/main.json | 6 +++--- avm/res/virtual-machine-images/image-template/README.md | 8 ++++---- avm/res/virtual-machine-images/image-template/main.bicep | 4 ++-- avm/res/virtual-machine-images/image-template/main.json | 6 +++--- 10 files changed, 22 insertions(+), 22 deletions(-) diff --git a/avm/res/resource-graph/query/README.md b/avm/res/resource-graph/query/README.md index a0d9171de4..253226548f 100644 --- a/avm/res/resource-graph/query/README.md +++ b/avm/res/resource-graph/query/README.md @@ -278,7 +278,7 @@ module query 'br/public:avm/res/resource-graph/query:' = { | Parameter | Type | Description | | :-- | :-- | :-- | -| [`name`](#parameter-name) | string | Name of the Resource Graph Query. | +| [`name`](#parameter-name) | string | The name of the Resource Graph Query. | | [`query`](#parameter-query) | string | KQL query that will be graph. | **Optional parameters** @@ -294,7 +294,7 @@ module query 'br/public:avm/res/resource-graph/query:' = { ### Parameter: `name` -Name of the Resource Graph Query. +The name of the Resource Graph Query. - Required: Yes - Type: string diff --git a/avm/res/resource-graph/query/main.bicep b/avm/res/resource-graph/query/main.bicep index c0d451a94a..469ed20814 100644 --- a/avm/res/resource-graph/query/main.bicep +++ b/avm/res/resource-graph/query/main.bicep @@ -6,7 +6,7 @@ metadata owner = 'Azure/module-maintainers' // Parameters // // ================ // -@description('Required. Name of the Resource Graph Query.') +@description('Required. The name of the Resource Graph Query.') param name string @description('Optional. Location for all resources.') diff --git a/avm/res/resource-graph/query/main.json b/avm/res/resource-graph/query/main.json index 64d9052655..cebf826c01 100644 --- a/avm/res/resource-graph/query/main.json +++ b/avm/res/resource-graph/query/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "8072514070285903960" + "templateHash": "923009628819731946" }, "name": "Resource Graph Queries", "description": "This module deploys a Resource Graph Query.", @@ -109,7 +109,7 @@ "name": { "type": "string", "metadata": { - "description": "Required. Name of the Resource Graph Query." + "description": "Required. The name of the Resource Graph Query." } }, "location": { diff --git a/avm/res/synapse/workspace/key/README.md b/avm/res/synapse/workspace/key/README.md index 68021da16a..8f91066119 100644 --- a/avm/res/synapse/workspace/key/README.md +++ b/avm/res/synapse/workspace/key/README.md @@ -24,7 +24,7 @@ This module deploys a Synapse Workspaces Key. | :-- | :-- | :-- | | [`isActiveCMK`](#parameter-isactivecmk) | bool | Used to activate the workspace after a customer managed key is provided. | | [`keyVaultResourceId`](#parameter-keyvaultresourceid) | string | The resource ID of a key vault to reference a customer managed key for encryption from. | -| [`name`](#parameter-name) | string | Encryption key name. | +| [`name`](#parameter-name) | string | The name of the Synapse Workspaces Key. | **Conditional parameters** @@ -48,7 +48,7 @@ The resource ID of a key vault to reference a customer managed key for encryptio ### Parameter: `name` -Encryption key name. +The name of the Synapse Workspaces Key. - Required: Yes - Type: string diff --git a/avm/res/synapse/workspace/key/main.bicep b/avm/res/synapse/workspace/key/main.bicep index e24333f15c..e05d5f768d 100644 --- a/avm/res/synapse/workspace/key/main.bicep +++ b/avm/res/synapse/workspace/key/main.bicep @@ -2,7 +2,7 @@ metadata name = 'Synapse Workspaces Keys' metadata description = 'This module deploys a Synapse Workspaces Key.' metadata owner = 'Azure/module-maintainers' -@description('Required. Encryption key name.') +@description('Required. The name of the Synapse Workspaces Key.') param name string @description('Conditional. The name of the parent Synapse Workspace. Required if the template is used in a standalone deployment.') diff --git a/avm/res/synapse/workspace/key/main.json b/avm/res/synapse/workspace/key/main.json index 85aed99df5..b966f02678 100644 --- a/avm/res/synapse/workspace/key/main.json +++ b/avm/res/synapse/workspace/key/main.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "2498604793784722860" + "templateHash": "29131182338463302" }, "name": "Synapse Workspaces Keys", "description": "This module deploys a Synapse Workspaces Key.", @@ -15,7 +15,7 @@ "name": { "type": "string", "metadata": { - "description": "Required. Encryption key name." + "description": "Required. The name of the Synapse Workspaces Key." } }, "workspaceName": { diff --git a/avm/res/synapse/workspace/main.json b/avm/res/synapse/workspace/main.json index 1d1b1b6994..c12bb64271 100644 --- a/avm/res/synapse/workspace/main.json +++ b/avm/res/synapse/workspace/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "13895345816421777976" + "templateHash": "2846633042311760037" }, "name": "Synapse Workspaces", "description": "This module deploys a Synapse Workspace.", @@ -976,7 +976,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "2498604793784722860" + "templateHash": "29131182338463302" }, "name": "Synapse Workspaces Keys", "description": "This module deploys a Synapse Workspaces Key.", @@ -986,7 +986,7 @@ "name": { "type": "string", "metadata": { - "description": "Required. Encryption key name." + "description": "Required. The name of the Synapse Workspaces Key." } }, "workspaceName": { diff --git a/avm/res/virtual-machine-images/image-template/README.md b/avm/res/virtual-machine-images/image-template/README.md index 3fb6df0ff5..18c11c37ec 100644 --- a/avm/res/virtual-machine-images/image-template/README.md +++ b/avm/res/virtual-machine-images/image-template/README.md @@ -509,13 +509,13 @@ module imageTemplate 'br/public:avm/res/virtual-machine-images/image-template: Date: Tue, 12 Mar 2024 18:14:30 +0000 Subject: [PATCH 11/73] fix: `resource-graph/query` workflow fix & update to enforce publish with source (#1261) ## Description - Update template to enforce publish with source - Fix bug in workflow trigger ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.resource-graph.query](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.resource-graph.query.yml/badge.svg?branch=fix%2Feriqua%2Fres-graph)](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.resource-graph.query.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [ ] Azure Verified Module updates: - [ ] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [ ] I'm sure there are no other open Pull Requests for the same update/change - [ ] I have run `Set-AVMModule` locally to generate the supporting module files. - [ ] My corresponding pipelines / checks run clean and green without any errors or warnings --- .github/workflows/avm.res.resource-graph.query.yml | 2 +- avm/res/resource-graph/query/README.md | 4 ++-- avm/res/resource-graph/query/main.bicep | 2 +- avm/res/resource-graph/query/main.json | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/avm.res.resource-graph.query.yml b/.github/workflows/avm.res.resource-graph.query.yml index 3a4d5a2c9b..9d3d3135bf 100644 --- a/.github/workflows/avm.res.resource-graph.query.yml +++ b/.github/workflows/avm.res.resource-graph.query.yml @@ -27,7 +27,7 @@ on: - ".github/actions/templates/avm-**" - ".github/workflows/avm.template.module.yml" - ".github/workflows/avm.res.resource-graph.query.yml" - - "avm/res/resource-graph.query/**" + - "avm/res/resource-graph/query/**" - "avm/utilities/pipelines/**" - "!*/**/README.md" diff --git a/avm/res/resource-graph/query/README.md b/avm/res/resource-graph/query/README.md index 253226548f..828aa6e04d 100644 --- a/avm/res/resource-graph/query/README.md +++ b/avm/res/resource-graph/query/README.md @@ -279,7 +279,7 @@ module query 'br/public:avm/res/resource-graph/query:' = { | Parameter | Type | Description | | :-- | :-- | :-- | | [`name`](#parameter-name) | string | The name of the Resource Graph Query. | -| [`query`](#parameter-query) | string | KQL query that will be graph. | +| [`query`](#parameter-query) | string | The KQL query that will be graph. | **Optional parameters** @@ -301,7 +301,7 @@ The name of the Resource Graph Query. ### Parameter: `query` -KQL query that will be graph. +The KQL query that will be graph. - Required: Yes - Type: string diff --git a/avm/res/resource-graph/query/main.bicep b/avm/res/resource-graph/query/main.bicep index 469ed20814..c5e14f413c 100644 --- a/avm/res/resource-graph/query/main.bicep +++ b/avm/res/resource-graph/query/main.bicep @@ -24,7 +24,7 @@ param tags object? @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -@description('Required. KQL query that will be graph.') +@description('Required. The KQL query that will be graph.') param query string @description('Optional. The description of a graph query.') diff --git a/avm/res/resource-graph/query/main.json b/avm/res/resource-graph/query/main.json index cebf826c01..c83a3bcccc 100644 --- a/avm/res/resource-graph/query/main.json +++ b/avm/res/resource-graph/query/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "923009628819731946" + "templateHash": "11608089387685875892" }, "name": "Resource Graph Queries", "description": "This module deploys a Resource Graph Query.", @@ -148,7 +148,7 @@ "query": { "type": "string", "metadata": { - "description": "Required. KQL query that will be graph." + "description": "Required. The KQL query that will be graph." } }, "queryDescription": { From d2d05832cfd0e07603238c7c34114ba4ddc95c25 Mon Sep 17 00:00:00 2001 From: Javier Cevallos Date: Tue, 12 Mar 2024 15:33:35 -0700 Subject: [PATCH 12/73] Minor Update (#1262) ## Description Just a minor update to improve readability. ## Type of Change - [x ] Update to documentation ## Checklist - [x ] I'm sure there are no other open Pull Requests for the same update/change - [ ] I have run `Set-AVMModule` locally to generate the supporting module files. - [ ] My corresponding pipelines / checks run clean and green without any errors or warnings --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9f2ff5ae29..4903681704 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ To provide our customers with a unified experience, Azure Verified Modules ([AVM](https://aka.ms/AVM)) will become the single Microsoft standard for Bicep modules, published to the Public Bicep Registry, via this repository. -Going forward, new modules will be need to be developed and published in accordance with the [AVM specifications](https://azure.github.io/Azure-Verified-Modules/specs/module-specs/). Module proposals for new, non-AVM modules will no longer be accepted. To propose a new AVM module, you can file a Module Proposal, [here](https://aka.ms/AVM/ModuleProposal). +Going forward, new modules will need to be developed and published in accordance with the [AVM specifications](https://azure.github.io/Azure-Verified-Modules/specs/module-specs/). Module proposals for new, non-AVM modules will no longer be accepted. To propose a new AVM module, you can file a Module Proposal, [here](https://aka.ms/AVM/ModuleProposal). Existing non-AVM modules will be retired or migrated to AVM. To provide continued access for existing customers, non-AVM modules formerly published in the registry will be kept there indefinitely, but their source code will be replaced with an informational notice and a pointer to their successor in AVM, when applicable. Over time, VS code intellisense support for the old, non-AVM modules will also be removed - while existing references will keep working. From 0d8cdd5838acf61b26ec4a41b9e7a5429ba93885 Mon Sep 17 00:00:00 2001 From: Kris Baranek Date: Wed, 13 Mar 2024 11:27:00 +0100 Subject: [PATCH 13/73] fix: unorphaned `avm/res/maintenance/maintenance-configuration` (#1240) ## Description Unorphaned `avm/res/maintenance/maintenance-configuration` module. ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.maintenance.maintenance-configuration](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.maintenance.maintenance-configuration.yml/badge.svg?branch=users%2Fkrbar%2FunorphanMaintenanceConfig)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.maintenance.maintenance-configuration.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [x] Azure Verified Module updates: - [x] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [x] I have run `Set-AVMModule` locally to generate the supporting module files. - [x] My corresponding pipelines / checks run clean and green without any errors or warnings --- avm/res/maintenance/maintenance-configuration/ORPHANED.md | 4 ---- avm/res/maintenance/maintenance-configuration/README.md | 5 ----- 2 files changed, 9 deletions(-) delete mode 100644 avm/res/maintenance/maintenance-configuration/ORPHANED.md diff --git a/avm/res/maintenance/maintenance-configuration/ORPHANED.md b/avm/res/maintenance/maintenance-configuration/ORPHANED.md deleted file mode 100644 index ef8fa911d2..0000000000 --- a/avm/res/maintenance/maintenance-configuration/ORPHANED.md +++ /dev/null @@ -1,4 +0,0 @@ -⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ - -- Only security and bug fixes are being handled by the AVM core team at present. -- If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! \ No newline at end of file diff --git a/avm/res/maintenance/maintenance-configuration/README.md b/avm/res/maintenance/maintenance-configuration/README.md index 5e2cb2eefb..6d4e9519e5 100644 --- a/avm/res/maintenance/maintenance-configuration/README.md +++ b/avm/res/maintenance/maintenance-configuration/README.md @@ -1,10 +1,5 @@ # Maintenance Configurations `[Microsoft.Maintenance/maintenanceConfigurations]` -> ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ -> -> - Only security and bug fixes are being handled by the AVM core team at present. -> - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! - This module deploys a Maintenance Configuration. ## Navigation From c6a63667733ba5e42fa830fab6604672a6b5d922 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Mar 2024 12:08:58 +0000 Subject: [PATCH 14/73] chore(deps-dev): bump follow-redirects from 1.14.9 to 1.15.4 (#781) Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.9 to 1.15.4.

Commits
  • 6585820 Release version 1.15.4 of the npm package.
  • 7a6567e Disallow bracketed hostnames.
  • 05629af Prefer native URL instead of deprecated url.parse.
  • 1cba8e8 Prefer native URL instead of legacy url.resolve.
  • 72bc2a4 Simplify _processResponse error handling.
  • 3d42aec Add bracket tests.
  • bcbb096 Do not directly set Error properties.
  • 192dbe7 Release version 1.15.3 of the npm package.
  • bd8c81e Fix resource leak on destroy.
  • 9c728c3 Split linting and testing.
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=follow-redirects&package-manager=npm_and_yarn&previous-version=1.14.9&new-version=1.15.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/Azure/bicep-registry-modules/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> --- package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 438ea8e683..a89764c251 100644 --- a/package-lock.json +++ b/package-lock.json @@ -680,9 +680,9 @@ "dev": true }, "node_modules/follow-redirects": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", + "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", "dev": true, "funding": [ { @@ -1863,9 +1863,9 @@ "dev": true }, "follow-redirects": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", + "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", "dev": true }, "form-data": { From f2ad8df2f15be6611aab000e71ea9d6f61e5a9c0 Mon Sep 17 00:00:00 2001 From: Bryan <117635118+bryansan-msft@users.noreply.github.com> Date: Wed, 13 Mar 2024 16:01:39 +0100 Subject: [PATCH 15/73] fix: Force partition key parameter and Fix hierarchical partition key deployment and analytical store enablement (#1223) ## Description - Added more tests covering most NoSQL API and Account focused configurations. - Removed non-related NoSQL API tests from its test suite (They were already covered by waf-aligned and plain test suite). - Make partition key path parameter mandatory. - Fixes #1222 - Add "/" to partition key path if the user doesn't specify it to avoid errors when it's missing - Added user defined types for better consumer experience and intelisense. - Closes #1227 - Fixed an issue where deployment of a hierarchical partition key would fail even though it was allowed through parameter. - Fixes #1229 - Fixed an issue where you were forced to have RUs both in Container and Database due to default values being used. It was impossible to have RUs only at one level - Fixes #1226 - Fixed an issue where analytical store ttl couldn't be enabled since there was missing a parameter (enableAnalyticalStore) at account level - Fixes #1225 - Allow disabling local auth for NoSQL API as it is the recommended configuration when using managed identity's - Closes #1228 ## Remarks - I have had to hardcode the region where the tests are being deployed to eastus as the pipeline is picking up a random region which might have new cosmosdb constraints or not supported features that the tests need. ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.document-db.database-account](https://github.com/bryansan-msft/fork-bicep-registry-modules/actions/workflows/avm.res.document-db.database-account.yml/badge.svg)](https://github.com/bryansan-msft/fork-bicep-registry-modules/actions/workflows/avm.res.document-db.database-account.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [ ] Azure Verified Module updates: - [x] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [x] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [x] The bug was found by the module author, and no one has opened an issue to report it yet. - [x] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [x] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [x] I have run `Set-AVMModule` locally to generate the supporting module files. - [x] My corresponding pipelines / checks run clean and green without any errors or warnings --- .../document-db/database-account/README.md | 3067 +++++++++++------ .../document-db/database-account/main.bicep | 124 +- .../document-db/database-account/main.json | 323 +- .../database-account/sql-database/README.md | 9 +- .../sql-database/container/README.md | 37 +- .../sql-database/container/main.bicep | 21 +- .../sql-database/container/main.json | 33 +- .../database-account/sql-database/main.bicep | 22 +- .../database-account/sql-database/main.json | 70 +- .../tests/e2e/analytical/main.test.bicep | 58 + .../e2e/autoFailoverOff/dependencies.bicep | 46 + .../tests/e2e/autoFailoverOff/main.test.bicep | 77 + .../tests/e2e/consistency/main.test.bicep | 60 + .../tests/e2e/continousBckup/main.test.bicep | 59 + .../tests/e2e/defaults/main.test.bicep | 11 +- .../tests/e2e/disableLocal/main.test.bicep | 57 + .../tests/e2e/gremlindb/main.test.bicep | 21 +- .../tests/e2e/mongodb/main.test.bicep | 19 +- .../tests/e2e/periodicBckup/main.test.bicep | 61 + .../tests/e2e/plain/dependencies.bicep | 37 +- .../tests/e2e/plain/main.test.bicep | 41 +- .../tests/e2e/sqldb/dependencies.bicep | 117 - .../tests/e2e/sqldb/main.test.bicep | 301 +- .../tests/e2e/systemMi/main.test.bicep | 55 + .../tests/e2e/userMi/dependencies.bicep | 16 + .../tests/e2e/userMi/main.test.bicep | 73 + .../tests/e2e/waf-aligned/main.test.bicep | 35 +- .../tests/e2e/zoneRedundant/main.test.bicep | 52 + 28 files changed, 3374 insertions(+), 1528 deletions(-) create mode 100644 avm/res/document-db/database-account/tests/e2e/analytical/main.test.bicep create mode 100644 avm/res/document-db/database-account/tests/e2e/autoFailoverOff/dependencies.bicep create mode 100644 avm/res/document-db/database-account/tests/e2e/autoFailoverOff/main.test.bicep create mode 100644 avm/res/document-db/database-account/tests/e2e/consistency/main.test.bicep create mode 100644 avm/res/document-db/database-account/tests/e2e/continousBckup/main.test.bicep create mode 100644 avm/res/document-db/database-account/tests/e2e/disableLocal/main.test.bicep create mode 100644 avm/res/document-db/database-account/tests/e2e/periodicBckup/main.test.bicep delete mode 100644 avm/res/document-db/database-account/tests/e2e/sqldb/dependencies.bicep create mode 100644 avm/res/document-db/database-account/tests/e2e/systemMi/main.test.bicep create mode 100644 avm/res/document-db/database-account/tests/e2e/userMi/dependencies.bicep create mode 100644 avm/res/document-db/database-account/tests/e2e/userMi/main.test.bicep create mode 100644 avm/res/document-db/database-account/tests/e2e/zoneRedundant/main.test.bicep diff --git a/avm/res/document-db/database-account/README.md b/avm/res/document-db/database-account/README.md index 5202d4df23..00937cf54e 100644 --- a/avm/res/document-db/database-account/README.md +++ b/avm/res/document-db/database-account/README.md @@ -36,16 +36,25 @@ 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/document-db/database-account:`. -- [Using only defaults](#example-1-using-only-defaults) -- [Germlin Database](#example-2-germlin-database) -- [Mongo Database](#example-3-mongo-database) -- [Plain](#example-4-plain) -- [SQL Database](#example-5-sql-database) -- [WAF-aligned](#example-6-waf-aligned) - -### Example 1: _Using only defaults_ - -This instance deploys the module with the minimum set of required parameters. +- [Using analytical storage](#example-1-using-analytical-storage) +- [Without automatic failover](#example-2-without-automatic-failover) +- [Using bounded consistency](#example-3-using-bounded-consistency) +- [Enabling continous backups](#example-4-enabling-continous-backups) +- [Using only defaults](#example-5-using-only-defaults) +- [Disabling local authentication. i.e. access keys](#example-6-disabling-local-authentication-ie-access-keys) +- [Gremlin Database](#example-7-gremlin-database) +- [Mongo Database](#example-8-mongo-database) +- [Using periodic backups](#example-9-using-periodic-backups) +- [Plain](#example-10-plain) +- [SQL Database](#example-11-sql-database) +- [Deploying with a System-Assigned Identity](#example-12-deploying-with-a-system-assigned-identity) +- [Deploying with a User-Assigned Identity](#example-13-deploying-with-a-user-assigned-identity) +- [WAF-aligned](#example-14-waf-aligned) +- [Using zone redundant regions](#example-15-using-zone-redundant-regions) + +### Example 1: _Using analytical storage_ + +This instance deploys the module with analytical storage enabled.
@@ -54,7 +63,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dddamin' + name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddaanl' params: { // Required parameters locations: [ @@ -64,9 +73,15 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: locationName: '' } ] - name: 'dddamin001' + name: 'analytical' // Non-required parameters + enableAnalyticalStorage: true location: '' + sqlDatabases: [ + { + name: 'empty-database' + } + ] } } ``` @@ -94,11 +109,21 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: ] }, "name": { - "value": "dddamin001" + "value": "analytical" }, // Non-required parameters + "enableAnalyticalStorage": { + "value": true + }, "location": { "value": "" + }, + "sqlDatabases": { + "value": [ + { + "name": "empty-database" + } + ] } } } @@ -107,9 +132,9 @@ module databaseAccount 'br/public:avm/res/document-db/database-account:

-### Example 2: _Germlin Database_ +### Example 2: _Without automatic failover_ -This instance deploys the module with a Gremlin Database. +This instance deploys the module disabling automatic failover.

@@ -118,7 +143,7 @@ This instance deploys the module with a Gremlin Database. ```bicep module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dddagrm' + name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddaauo' params: { // Required parameters locations: [ @@ -133,100 +158,15 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: locationName: '' } ] - name: 'dddagrm002' + name: 'auto-failover-off' // Non-required parameters - capabilitiesToAdd: [ - 'EnableGremlin' - ] - diagnosticSettings: [ - { - eventHubAuthorizationRuleResourceId: '' - eventHubName: '' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - name: 'customSetting' - storageAccountResourceId: '' - workspaceResourceId: '' - } - ] - gremlinDatabases: [ - { - graphs: [ - { - indexingPolicy: { - automatic: true - } - name: 'car_collection' - partitionKeyPaths: [ - '/car_id' - ] - } - { - indexingPolicy: { - automatic: true - } - name: 'truck_collection' - partitionKeyPaths: [ - '/truck_id' - ] - } - ] - name: 'gdb-dddagrm-001' - throughput: 10000 - } - { - graphs: [ - { - indexingPolicy: { - automatic: true - } - name: 'bike_collection' - partitionKeyPaths: [ - '/bike_id' - ] - } - { - indexingPolicy: { - automatic: true - } - name: 'bicycle_collection' - partitionKeyPaths: [ - '/bicycle_id' - ] - } - ] - name: 'gdb-dddagrm-002' - } - ] + automaticFailover: false location: '' - managedIdentities: { - systemAssigned: true - } - roleAssignments: [ - { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: 'Owner' - } - { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - } + sqlDatabases: [ { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: '' + name: 'empty-database' } ] - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } } } ``` @@ -259,114 +199,21 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: ] }, "name": { - "value": "dddagrm002" + "value": "auto-failover-off" }, // Non-required parameters - "capabilitiesToAdd": { - "value": [ - "EnableGremlin" - ] - }, - "diagnosticSettings": { - "value": [ - { - "eventHubAuthorizationRuleResourceId": "", - "eventHubName": "", - "metricCategories": [ - { - "category": "AllMetrics" - } - ], - "name": "customSetting", - "storageAccountResourceId": "", - "workspaceResourceId": "" - } - ] - }, - "gremlinDatabases": { - "value": [ - { - "graphs": [ - { - "indexingPolicy": { - "automatic": true - }, - "name": "car_collection", - "partitionKeyPaths": [ - "/car_id" - ] - }, - { - "indexingPolicy": { - "automatic": true - }, - "name": "truck_collection", - "partitionKeyPaths": [ - "/truck_id" - ] - } - ], - "name": "gdb-dddagrm-001", - "throughput": 10000 - }, - { - "graphs": [ - { - "indexingPolicy": { - "automatic": true - }, - "name": "bike_collection", - "partitionKeyPaths": [ - "/bike_id" - ] - }, - { - "indexingPolicy": { - "automatic": true - }, - "name": "bicycle_collection", - "partitionKeyPaths": [ - "/bicycle_id" - ] - } - ], - "name": "gdb-dddagrm-002" - } - ] + "automaticFailover": { + "value": false }, "location": { "value": "" }, - "managedIdentities": { - "value": { - "systemAssigned": true - } - }, - "roleAssignments": { + "sqlDatabases": { "value": [ { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "Owner" - }, - { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" - }, - { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "" + "name": "empty-database" } ] - }, - "tags": { - "value": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } } } } @@ -375,9 +222,9 @@ module databaseAccount 'br/public:avm/res/document-db/database-account:

-### Example 3: _Mongo Database_ +### Example 3: _Using bounded consistency_ -This instance deploys the module with a Mongo Database. +This instance deploys the module specifying a default consistency level.

@@ -386,7 +233,7 @@ This instance deploys the module with a Mongo Database. ```bicep module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dddamng' + name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddabco' params: { // Required parameters locations: [ @@ -395,240 +242,105 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: isZoneRedundant: false locationName: '' } - { - failoverPriority: 1 - isZoneRedundant: false - locationName: '' - } ] - name: 'dddamng001' + name: 'bounded' // Non-required parameters - diagnosticSettings: [ + defaultConsistencyLevel: 'BoundedStaleness' + location: '' + maxIntervalInSeconds: 600 + maxStalenessPrefix: 200000 + sqlDatabases: [ { - eventHubAuthorizationRuleResourceId: '' - eventHubName: '' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - name: 'customSetting' - storageAccountResourceId: '' - workspaceResourceId: '' + name: 'empty-database' } ] - location: '' - managedIdentities: { - systemAssigned: true - } - mongodbDatabases: [ - { - collections: [ - { - indexes: [ - { - key: { - keys: [ - '_id' - ] - } - } - { - key: { - keys: [ - '$**' - ] - } - } - { - key: { - keys: [ - 'car_id' - 'car_model' - ] - } - options: { - unique: true - } - } - { - key: { - keys: [ - '_ts' - ] - } - options: { - expireAfterSeconds: 2629746 - } - } - ] - name: 'car_collection' - shardKey: { - car_id: 'Hash' - } - throughput: 600 - } - { - indexes: [ - { - key: { - keys: [ - '_id' - ] - } - } - { - key: { - keys: [ - '$**' - ] - } - } - { - key: { - keys: [ - 'truck_id' - 'truck_model' - ] - } - options: { - unique: true - } - } - { - key: { - keys: [ - '_ts' - ] - } - options: { - expireAfterSeconds: 2629746 - } - } - ] - name: 'truck_collection' - shardKey: { - truck_id: 'Hash' - } - } - ] - name: 'mdb-dddamng-001' - throughput: 800 - } + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "locations": { + "value": [ + { + "failoverPriority": 0, + "isZoneRedundant": false, + "locationName": "" + } + ] + }, + "name": { + "value": "bounded" + }, + // Non-required parameters + "defaultConsistencyLevel": { + "value": "BoundedStaleness" + }, + "location": { + "value": "" + }, + "maxIntervalInSeconds": { + "value": 600 + }, + "maxStalenessPrefix": { + "value": 200000 + }, + "sqlDatabases": { + "value": [ + { + "name": "empty-database" + } + ] + } + } +} +``` + +
+

+ +### Example 4: _Enabling continous backups_ + +This instance deploys the module enabling continous backups. + + +

+ +via Bicep module + +```bicep +module databaseAccount 'br/public:avm/res/document-db/database-account:' = { + name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddacbc' + params: { + // Required parameters + locations: [ { - collections: [ - { - indexes: [ - { - key: { - keys: [ - '_id' - ] - } - } - { - key: { - keys: [ - '$**' - ] - } - } - { - key: { - keys: [ - 'bike_id' - 'bike_model' - ] - } - options: { - unique: true - } - } - { - key: { - keys: [ - '_ts' - ] - } - options: { - expireAfterSeconds: 2629746 - } - } - ] - name: 'bike_collection' - shardKey: { - bike_id: 'Hash' - } - } - { - indexes: [ - { - key: { - keys: [ - '_id' - ] - } - } - { - key: { - keys: [ - '$**' - ] - } - } - { - key: { - keys: [ - 'bicycle_id' - 'bicycle_model' - ] - } - options: { - unique: true - } - } - { - key: { - keys: [ - '_ts' - ] - } - options: { - expireAfterSeconds: 2629746 - } - } - ] - name: 'bicycle_collection' - shardKey: { - bicycle_id: 'Hash' - } - } - ] - name: 'mdb-dddamng-002' + failoverPriority: 0 + isZoneRedundant: false + locationName: '' } ] - roleAssignments: [ - { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: 'Owner' - } - { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - } + name: 'continous-bckup' + // Non-required parameters + backupPolicyContinuousTier: 'Continuous7Days' + backupPolicyType: 'Continuous' + location: '' + sqlDatabases: [ { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: '' + name: 'empty-database' } ] - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } } } ``` @@ -652,255 +364,1772 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: "failoverPriority": 0, "isZoneRedundant": false, "locationName": "" - }, - { - "failoverPriority": 1, - "isZoneRedundant": false, - "locationName": "" } ] }, "name": { - "value": "dddamng001" + "value": "continous-bckup" }, // Non-required parameters - "diagnosticSettings": { + "backupPolicyContinuousTier": { + "value": "Continuous7Days" + }, + "backupPolicyType": { + "value": "Continuous" + }, + "location": { + "value": "" + }, + "sqlDatabases": { "value": [ { - "eventHubAuthorizationRuleResourceId": "", + "name": "empty-database" + } + ] + } + } +} +``` + +
+

+ +### Example 5: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. + + +

+ +via Bicep module + +```bicep +module databaseAccount 'br/public:avm/res/document-db/database-account:' = { + name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddamin' + params: { + // Required parameters + locations: [ + { + failoverPriority: 0 + isZoneRedundant: false + locationName: '' + } + ] + name: 'dddamin001' + // Non-required parameters + location: '' + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "locations": { + "value": [ + { + "failoverPriority": 0, + "isZoneRedundant": false, + "locationName": "" + } + ] + }, + "name": { + "value": "dddamin001" + }, + // Non-required parameters + "location": { + "value": "" + } + } +} +``` + +
+

+ +### Example 6: _Disabling local authentication. i.e. access keys_ + +This instance deploys the module disabling local authentication. + + +

+ +via Bicep module + +```bicep +module databaseAccount 'br/public:avm/res/document-db/database-account:' = { + name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddadlo' + params: { + // Required parameters + locations: [ + { + failoverPriority: 0 + isZoneRedundant: false + locationName: '' + } + ] + name: 'local-auth-off' + // Non-required parameters + disableLocalAuth: true + location: '' + sqlDatabases: [ + { + name: 'empty-database' + } + ] + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "locations": { + "value": [ + { + "failoverPriority": 0, + "isZoneRedundant": false, + "locationName": "" + } + ] + }, + "name": { + "value": "local-auth-off" + }, + // Non-required parameters + "disableLocalAuth": { + "value": true + }, + "location": { + "value": "" + }, + "sqlDatabases": { + "value": [ + { + "name": "empty-database" + } + ] + } + } +} +``` + +
+

+ +### Example 7: _Gremlin Database_ + +This instance deploys the module with a Gremlin Database. + + +

+ +via Bicep module + +```bicep +module databaseAccount 'br/public:avm/res/document-db/database-account:' = { + name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddagrm' + params: { + // Required parameters + locations: [ + { + failoverPriority: 0 + isZoneRedundant: false + locationName: '' + } + { + failoverPriority: 1 + isZoneRedundant: false + locationName: '' + } + ] + name: 'dddagrm002' + // Non-required parameters + capabilitiesToAdd: [ + 'EnableGremlin' + ] + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + gremlinDatabases: [ + { + graphs: [ + { + indexingPolicy: { + automatic: true + } + name: 'car_collection' + partitionKeyPaths: [ + '/car_id' + ] + } + { + indexingPolicy: { + automatic: true + } + name: 'truck_collection' + partitionKeyPaths: [ + '/truck_id' + ] + } + ] + name: 'gdb-dddagrm-001' + throughput: 10000 + } + { + graphs: [ + { + indexingPolicy: { + automatic: true + } + name: 'bike_collection' + partitionKeyPaths: [ + '/bike_id' + ] + } + { + indexingPolicy: { + automatic: true + } + name: 'bicycle_collection' + partitionKeyPaths: [ + '/bicycle_id' + ] + } + ] + name: 'gdb-dddagrm-002' + } + ] + location: '' + managedIdentities: { + systemAssigned: true + } + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "locations": { + "value": [ + { + "failoverPriority": 0, + "isZoneRedundant": false, + "locationName": "" + }, + { + "failoverPriority": 1, + "isZoneRedundant": false, + "locationName": "" + } + ] + }, + "name": { + "value": "dddagrm002" + }, + // Non-required parameters + "capabilitiesToAdd": { + "value": [ + "EnableGremlin" + ] + }, + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "gremlinDatabases": { + "value": [ + { + "graphs": [ + { + "indexingPolicy": { + "automatic": true + }, + "name": "car_collection", + "partitionKeyPaths": [ + "/car_id" + ] + }, + { + "indexingPolicy": { + "automatic": true + }, + "name": "truck_collection", + "partitionKeyPaths": [ + "/truck_id" + ] + } + ], + "name": "gdb-dddagrm-001", + "throughput": 10000 + }, + { + "graphs": [ + { + "indexingPolicy": { + "automatic": true + }, + "name": "bike_collection", + "partitionKeyPaths": [ + "/bike_id" + ] + }, + { + "indexingPolicy": { + "automatic": true + }, + "name": "bicycle_collection", + "partitionKeyPaths": [ + "/bicycle_id" + ] + } + ], + "name": "gdb-dddagrm-002" + } + ] + }, + "location": { + "value": "" + }, + "managedIdentities": { + "value": { + "systemAssigned": true + } + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

+ +### Example 8: _Mongo Database_ + +This instance deploys the module with a Mongo Database. + + +

+ +via Bicep module + +```bicep +module databaseAccount 'br/public:avm/res/document-db/database-account:' = { + name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddamng' + params: { + // Required parameters + locations: [ + { + failoverPriority: 0 + isZoneRedundant: false + locationName: '' + } + { + failoverPriority: 1 + isZoneRedundant: false + locationName: '' + } + ] + name: 'dddamng001' + // Non-required parameters + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + location: '' + managedIdentities: { + systemAssigned: true + } + mongodbDatabases: [ + { + collections: [ + { + indexes: [ + { + key: { + keys: [ + '_id' + ] + } + } + { + key: { + keys: [ + '$**' + ] + } + } + { + key: { + keys: [ + 'car_id' + 'car_model' + ] + } + options: { + unique: true + } + } + { + key: { + keys: [ + '_ts' + ] + } + options: { + expireAfterSeconds: 2629746 + } + } + ] + name: 'car_collection' + shardKey: { + car_id: 'Hash' + } + throughput: 600 + } + { + indexes: [ + { + key: { + keys: [ + '_id' + ] + } + } + { + key: { + keys: [ + '$**' + ] + } + } + { + key: { + keys: [ + 'truck_id' + 'truck_model' + ] + } + options: { + unique: true + } + } + { + key: { + keys: [ + '_ts' + ] + } + options: { + expireAfterSeconds: 2629746 + } + } + ] + name: 'truck_collection' + shardKey: { + truck_id: 'Hash' + } + } + ] + name: 'mdb-dddamng-001' + throughput: 800 + } + { + collections: [ + { + indexes: [ + { + key: { + keys: [ + '_id' + ] + } + } + { + key: { + keys: [ + '$**' + ] + } + } + { + key: { + keys: [ + 'bike_id' + 'bike_model' + ] + } + options: { + unique: true + } + } + { + key: { + keys: [ + '_ts' + ] + } + options: { + expireAfterSeconds: 2629746 + } + } + ] + name: 'bike_collection' + shardKey: { + bike_id: 'Hash' + } + } + { + indexes: [ + { + key: { + keys: [ + '_id' + ] + } + } + { + key: { + keys: [ + '$**' + ] + } + } + { + key: { + keys: [ + 'bicycle_id' + 'bicycle_model' + ] + } + options: { + unique: true + } + } + { + key: { + keys: [ + '_ts' + ] + } + options: { + expireAfterSeconds: 2629746 + } + } + ] + name: 'bicycle_collection' + shardKey: { + bicycle_id: 'Hash' + } + } + ] + name: 'mdb-dddamng-002' + } + ] + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "locations": { + "value": [ + { + "failoverPriority": 0, + "isZoneRedundant": false, + "locationName": "" + }, + { + "failoverPriority": 1, + "isZoneRedundant": false, + "locationName": "" + } + ] + }, + "name": { + "value": "dddamng001" + }, + // Non-required parameters + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "location": { + "value": "" + }, + "managedIdentities": { + "value": { + "systemAssigned": true + } + }, + "mongodbDatabases": { + "value": [ + { + "collections": [ + { + "indexes": [ + { + "key": { + "keys": [ + "_id" + ] + } + }, + { + "key": { + "keys": [ + "$**" + ] + } + }, + { + "key": { + "keys": [ + "car_id", + "car_model" + ] + }, + "options": { + "unique": true + } + }, + { + "key": { + "keys": [ + "_ts" + ] + }, + "options": { + "expireAfterSeconds": 2629746 + } + } + ], + "name": "car_collection", + "shardKey": { + "car_id": "Hash" + }, + "throughput": 600 + }, + { + "indexes": [ + { + "key": { + "keys": [ + "_id" + ] + } + }, + { + "key": { + "keys": [ + "$**" + ] + } + }, + { + "key": { + "keys": [ + "truck_id", + "truck_model" + ] + }, + "options": { + "unique": true + } + }, + { + "key": { + "keys": [ + "_ts" + ] + }, + "options": { + "expireAfterSeconds": 2629746 + } + } + ], + "name": "truck_collection", + "shardKey": { + "truck_id": "Hash" + } + } + ], + "name": "mdb-dddamng-001", + "throughput": 800 + }, + { + "collections": [ + { + "indexes": [ + { + "key": { + "keys": [ + "_id" + ] + } + }, + { + "key": { + "keys": [ + "$**" + ] + } + }, + { + "key": { + "keys": [ + "bike_id", + "bike_model" + ] + }, + "options": { + "unique": true + } + }, + { + "key": { + "keys": [ + "_ts" + ] + }, + "options": { + "expireAfterSeconds": 2629746 + } + } + ], + "name": "bike_collection", + "shardKey": { + "bike_id": "Hash" + } + }, + { + "indexes": [ + { + "key": { + "keys": [ + "_id" + ] + } + }, + { + "key": { + "keys": [ + "$**" + ] + } + }, + { + "key": { + "keys": [ + "bicycle_id", + "bicycle_model" + ] + }, + "options": { + "unique": true + } + }, + { + "key": { + "keys": [ + "_ts" + ] + }, + "options": { + "expireAfterSeconds": 2629746 + } + } + ], + "name": "bicycle_collection", + "shardKey": { + "bicycle_id": "Hash" + } + } + ], + "name": "mdb-dddamng-002" + } + ] + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

+ +### Example 9: _Using periodic backups_ + +This instance deploys the module enabling periodic backups. + + +

+ +via Bicep module + +```bicep +module databaseAccount 'br/public:avm/res/document-db/database-account:' = { + name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddapbc' + params: { + // Required parameters + locations: [ + { + failoverPriority: 0 + isZoneRedundant: false + locationName: '' + } + ] + name: 'periodic-bckup' + // Non-required parameters + backupIntervalInMinutes: 300 + backupPolicyType: 'Periodic' + backupRetentionIntervalInHours: 16 + backupStorageRedundancy: 'Zone' + location: '' + sqlDatabases: [ + { + name: 'empty-database' + } + ] + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "locations": { + "value": [ + { + "failoverPriority": 0, + "isZoneRedundant": false, + "locationName": "" + } + ] + }, + "name": { + "value": "periodic-bckup" + }, + // Non-required parameters + "backupIntervalInMinutes": { + "value": 300 + }, + "backupPolicyType": { + "value": "Periodic" + }, + "backupRetentionIntervalInHours": { + "value": 16 + }, + "backupStorageRedundancy": { + "value": "Zone" + }, + "location": { + "value": "" + }, + "sqlDatabases": { + "value": [ + { + "name": "empty-database" + } + ] + } + } +} +``` + +
+

+ +### Example 10: _Plain_ + +This instance deploys the module without a Database. + + +

+ +via Bicep module + +```bicep +module databaseAccount 'br/public:avm/res/document-db/database-account:' = { + name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddapln' + params: { + // Required parameters + locations: [ + { + failoverPriority: 0 + isZoneRedundant: false + locationName: '' + } + ] + name: 'dddapln001' + // Non-required parameters + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "locations": { + "value": [ + { + "failoverPriority": 0, + "isZoneRedundant": false, + "locationName": "" + } + ] + }, + "name": { + "value": "dddapln001" + }, + // Non-required parameters + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", "eventHubName": "", "metricCategories": [ { - "category": "AllMetrics" + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

+ +### Example 11: _SQL Database_ + +This instance deploys the module with a SQL Database. + + +

+ +via Bicep module + +```bicep +module databaseAccount 'br/public:avm/res/document-db/database-account:' = { + name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddasql' + params: { + // Required parameters + locations: [ + { + failoverPriority: 0 + isZoneRedundant: false + locationName: '' + } + ] + name: 'dddasql001' + // Non-required parameters + enableAnalyticalStorage: true + location: '' + sqlDatabases: [ + { + containers: [ + { + analyticalStorageTtl: 0 + conflictResolutionPolicy: { + conflictResolutionPath: '/myCustomId' + mode: 'LastWriterWins' + } + defaultTtl: 1000 + indexingPolicy: { + automatic: true + } + kind: 'Hash' + name: 'container-001' + paths: [ + '/myPartitionKey' + ] + throughput: 600 + uniqueKeyPolicyKeys: [ + { + paths: [ + '/firstName' + ] + } + { + paths: [ + '/lastName' + ] + } + ] + } + ] + name: 'all-configs-specified' + } + { + containers: [ + { + indexingPolicy: { + automatic: true + } + name: 'container-001' + paths: [ + '/myPartitionKey' + ] + } + ] + name: 'automatic-indexing-policy' + } + { + containers: [ + { + conflictResolutionPolicy: { + conflictResolutionPath: '/myCustomId' + mode: 'LastWriterWins' + } + name: 'container-001' + paths: [ + '/myPartitionKey' + ] + } + ] + name: 'last-writer-conflict-resolution-policy' + } + { + containers: [ + { + analyticalStorageTtl: 1000 + name: 'container-001' + paths: [ + '/myPartitionKey' + ] + } + ] + name: 'fixed-analytical-ttl' + } + { + containers: [ + { + analyticalStorageTtl: -1 + name: 'container-001' + paths: [ + '/myPartitionKey' + ] + } + ] + name: 'infinite-analytical-ttl' + } + { + containers: [ + { + defaultTtl: 1000 + name: 'container-001' + paths: [ + '/myPartitionKey' + ] + } + ] + name: 'document-ttl' + } + { + containers: [ + { + name: 'container-001' + paths: [ + '/myPartitionKey' + ] + uniqueKeyPolicyKeys: [ + { + paths: [ + '/firstName' + ] + } + { + paths: [ + '/lastName' + ] + } + ] + } + ] + name: 'unique-key-policy' + } + { + containers: [ + { + name: 'container-003' + paths: [ + '/myPartitionKey' + ] + throughput: 500 + } + ] + name: 'db-and-container-fixed-throughput-level' + throughput: 500 + } + { + containers: [ + { + name: 'container-003' + paths: [ + '/myPartitionKey' + ] + throughput: 500 + } + ] + name: 'container-fixed-throughput-level' + } + { + containers: [ + { + name: 'container-003' + paths: [ + '/myPartitionKey' + ] + } + ] + name: 'database-fixed-throughput-level' + throughput: 500 + } + { + autoscaleSettingsMaxThroughput: 1000 + containers: [ + { + autoscaleSettingsMaxThroughput: 1000 + name: 'container-003' + paths: [ + '/myPartitionKey' + ] + } + ] + name: 'db-and-container-autoscale-level' + } + { + containers: [ + { + autoscaleSettingsMaxThroughput: 1000 + name: 'container-003' + paths: [ + '/myPartitionKey' + ] + } + ] + name: 'container-autoscale-level' + } + { + autoscaleSettingsMaxThroughput: 1000 + containers: [ + { + name: 'container-003' + paths: [ + '/myPartitionKey' + ] + } + ] + name: 'database-autoscale-level' + } + { + containers: [ + { + kind: 'MultiHash' + name: 'container-001' + paths: [ + '/myPartitionKey1' + '/myPartitionKey2' + '/myPartitionKey3' + ] + } + { + kind: 'MultiHash' + name: 'container-002' + paths: [ + 'myPartitionKey1' + 'myPartitionKey2' + 'myPartitionKey3' + ] + } + { + kind: 'Hash' + name: 'container-003' + paths: [ + '/myPartitionKey1' + ] + } + { + kind: 'Hash' + name: 'container-004' + paths: [ + 'myPartitionKey1' + ] + } + ] + name: 'all-partition-key-types' + } + { + containers: [] + name: 'empty-containers-array' + } + { + name: 'no-containers-specified' + } + ] + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "locations": { + "value": [ + { + "failoverPriority": 0, + "isZoneRedundant": false, + "locationName": "" + } + ] + }, + "name": { + "value": "dddasql001" + }, + // Non-required parameters + "enableAnalyticalStorage": { + "value": true + }, + "location": { + "value": "" + }, + "sqlDatabases": { + "value": [ + { + "containers": [ + { + "analyticalStorageTtl": 0, + "conflictResolutionPolicy": { + "conflictResolutionPath": "/myCustomId", + "mode": "LastWriterWins" + }, + "defaultTtl": 1000, + "indexingPolicy": { + "automatic": true + }, + "kind": "Hash", + "name": "container-001", + "paths": [ + "/myPartitionKey" + ], + "throughput": 600, + "uniqueKeyPolicyKeys": [ + { + "paths": [ + "/firstName" + ] + }, + { + "paths": [ + "/lastName" + ] + } + ] + } + ], + "name": "all-configs-specified" + }, + { + "containers": [ + { + "indexingPolicy": { + "automatic": true + }, + "name": "container-001", + "paths": [ + "/myPartitionKey" + ] + } + ], + "name": "automatic-indexing-policy" + }, + { + "containers": [ + { + "conflictResolutionPolicy": { + "conflictResolutionPath": "/myCustomId", + "mode": "LastWriterWins" + }, + "name": "container-001", + "paths": [ + "/myPartitionKey" + ] + } + ], + "name": "last-writer-conflict-resolution-policy" + }, + { + "containers": [ + { + "analyticalStorageTtl": 1000, + "name": "container-001", + "paths": [ + "/myPartitionKey" + ] + } + ], + "name": "fixed-analytical-ttl" + }, + { + "containers": [ + { + "analyticalStorageTtl": -1, + "name": "container-001", + "paths": [ + "/myPartitionKey" + ] + } + ], + "name": "infinite-analytical-ttl" + }, + { + "containers": [ + { + "defaultTtl": 1000, + "name": "container-001", + "paths": [ + "/myPartitionKey" + ] } ], - "name": "customSetting", - "storageAccountResourceId": "", - "workspaceResourceId": "" - } - ] - }, - "location": { - "value": "" - }, - "managedIdentities": { - "value": { - "systemAssigned": true - } - }, - "mongodbDatabases": { - "value": [ + "name": "document-ttl" + }, { - "collections": [ + "containers": [ { - "indexes": [ - { - "key": { - "keys": [ - "_id" - ] - } - }, - { - "key": { - "keys": [ - "$**" - ] - } - }, - { - "key": { - "keys": [ - "car_id", - "car_model" - ] - }, - "options": { - "unique": true - } - }, - { - "key": { - "keys": [ - "_ts" - ] - }, - "options": { - "expireAfterSeconds": 2629746 - } - } + "name": "container-001", + "paths": [ + "/myPartitionKey" ], - "name": "car_collection", - "shardKey": { - "car_id": "Hash" - }, - "throughput": 600 - }, - { - "indexes": [ - { - "key": { - "keys": [ - "_id" - ] - } - }, - { - "key": { - "keys": [ - "$**" - ] - } - }, + "uniqueKeyPolicyKeys": [ { - "key": { - "keys": [ - "truck_id", - "truck_model" - ] - }, - "options": { - "unique": true - } + "paths": [ + "/firstName" + ] }, { - "key": { - "keys": [ - "_ts" - ] - }, - "options": { - "expireAfterSeconds": 2629746 - } + "paths": [ + "/lastName" + ] } - ], - "name": "truck_collection", - "shardKey": { - "truck_id": "Hash" - } + ] } ], - "name": "mdb-dddamng-001", - "throughput": 800 + "name": "unique-key-policy" }, { - "collections": [ + "containers": [ { - "indexes": [ - { - "key": { - "keys": [ - "_id" - ] - } - }, - { - "key": { - "keys": [ - "$**" - ] - } - }, - { - "key": { - "keys": [ - "bike_id", - "bike_model" - ] - }, - "options": { - "unique": true - } - }, - { - "key": { - "keys": [ - "_ts" - ] - }, - "options": { - "expireAfterSeconds": 2629746 - } - } + "name": "container-003", + "paths": [ + "/myPartitionKey" ], - "name": "bike_collection", - "shardKey": { - "bike_id": "Hash" - } - }, + "throughput": 500 + } + ], + "name": "db-and-container-fixed-throughput-level", + "throughput": 500 + }, + { + "containers": [ { - "indexes": [ - { - "key": { - "keys": [ - "_id" - ] - } - }, - { - "key": { - "keys": [ - "$**" - ] - } - }, - { - "key": { - "keys": [ - "bicycle_id", - "bicycle_model" - ] - }, - "options": { - "unique": true - } - }, - { - "key": { - "keys": [ - "_ts" - ] - }, - "options": { - "expireAfterSeconds": 2629746 - } - } + "name": "container-003", + "paths": [ + "/myPartitionKey" ], - "name": "bicycle_collection", - "shardKey": { - "bicycle_id": "Hash" - } + "throughput": 500 + } + ], + "name": "container-fixed-throughput-level" + }, + { + "containers": [ + { + "name": "container-003", + "paths": [ + "/myPartitionKey" + ] + } + ], + "name": "database-fixed-throughput-level", + "throughput": 500 + }, + { + "autoscaleSettingsMaxThroughput": 1000, + "containers": [ + { + "autoscaleSettingsMaxThroughput": 1000, + "name": "container-003", + "paths": [ + "/myPartitionKey" + ] + } + ], + "name": "db-and-container-autoscale-level" + }, + { + "containers": [ + { + "autoscaleSettingsMaxThroughput": 1000, + "name": "container-003", + "paths": [ + "/myPartitionKey" + ] + } + ], + "name": "container-autoscale-level" + }, + { + "autoscaleSettingsMaxThroughput": 1000, + "containers": [ + { + "name": "container-003", + "paths": [ + "/myPartitionKey" + ] } ], - "name": "mdb-dddamng-002" - } - ] - }, - "roleAssignments": { - "value": [ + "name": "database-autoscale-level" + }, { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "Owner" + "containers": [ + { + "kind": "MultiHash", + "name": "container-001", + "paths": [ + "/myPartitionKey1", + "/myPartitionKey2", + "/myPartitionKey3" + ] + }, + { + "kind": "MultiHash", + "name": "container-002", + "paths": [ + "myPartitionKey1", + "myPartitionKey2", + "myPartitionKey3" + ] + }, + { + "kind": "Hash", + "name": "container-003", + "paths": [ + "/myPartitionKey1" + ] + }, + { + "kind": "Hash", + "name": "container-004", + "paths": [ + "myPartitionKey1" + ] + } + ], + "name": "all-partition-key-types" }, { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + "containers": [], + "name": "empty-containers-array" }, { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "" + "name": "no-containers-specified" } ] - }, - "tags": { - "value": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } } } } @@ -909,9 +2138,9 @@ module databaseAccount 'br/public:avm/res/document-db/database-account:

-### Example 4: _Plain_ +### Example 12: _Deploying with a System-Assigned Identity_ -This instance deploys the module without a Database. +This instance deploys the module with an assigned system assigned managed identity.

@@ -920,7 +2149,7 @@ This instance deploys the module without a Database. ```bicep module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dddapln' + name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddasmi' params: { // Required parameters locations: [ @@ -929,54 +2158,12 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: isZoneRedundant: false locationName: '' } - { - failoverPriority: 1 - isZoneRedundant: false - locationName: '' - } ] - name: 'dddapln001' + name: 'system-mi' // Non-required parameters - diagnosticSettings: [ - { - eventHubAuthorizationRuleResourceId: '' - eventHubName: '' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - name: 'customSetting' - storageAccountResourceId: '' - workspaceResourceId: '' - } - ] location: '' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - roleAssignments: [ - { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: 'Owner' - } - { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - } - { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: '' - } - ] - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' + managedIdentities: { + systemAssigned: true } } } @@ -1001,67 +2188,19 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: "failoverPriority": 0, "isZoneRedundant": false, "locationName": "" - }, - { - "failoverPriority": 1, - "isZoneRedundant": false, - "locationName": "" } ] }, "name": { - "value": "dddapln001" + "value": "system-mi" }, // Non-required parameters - "diagnosticSettings": { - "value": [ - { - "eventHubAuthorizationRuleResourceId": "", - "eventHubName": "", - "metricCategories": [ - { - "category": "AllMetrics" - } - ], - "name": "customSetting", - "storageAccountResourceId": "", - "workspaceResourceId": "" - } - ] - }, "location": { "value": "" }, - "lock": { - "value": { - "kind": "CanNotDelete", - "name": "myCustomLockName" - } - }, - "roleAssignments": { - "value": [ - { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "Owner" - }, - { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" - }, - { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "" - } - ] - }, - "tags": { + "managedIdentities": { "value": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" + "systemAssigned": true } } } @@ -1071,9 +2210,9 @@ module databaseAccount 'br/public:avm/res/document-db/database-account:

-### Example 5: _SQL Database_ +### Example 13: _Deploying with a User-Assigned Identity_ -This instance deploys the module with a SQL Database. +This instance deploys the module with an assigned user assigned managed identity.

@@ -1082,159 +2221,23 @@ This instance deploys the module with a SQL Database. ```bicep module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dddasql' + name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddaumi' params: { // Required parameters locations: [ { - failoverPriority: 0 - isZoneRedundant: false - locationName: '' - } - { - failoverPriority: 1 - isZoneRedundant: false - locationName: '' - } - ] - name: 'dddasql001' - // Non-required parameters - diagnosticSettings: [ - { - eventHubAuthorizationRuleResourceId: '' - eventHubName: '' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - name: 'customSetting' - storageAccountResourceId: '' - workspaceResourceId: '' - } - ] - location: '' - managedIdentities: { - userAssignedResourceIds: [ - '' - ] - } - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - '' - ] - service: 'Sql' - subnetResourceId: '' - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } - } - { - privateDnsZoneResourceIds: [ - '' - ] - service: 'Sql' - subnetResourceId: '' - } - ] - roleAssignments: [ - { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: 'Owner' - } - { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - } - { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: '' - } - ] - sqlDatabases: [ - { - containers: [ - { - analyticalStorageTtl: 0 - conflictResolutionPolicy: { - conflictResolutionPath: '/myCustomId' - mode: 'LastWriterWins' - } - defaultTtl: 1000 - indexingPolicy: { - automatic: true - } - kind: 'Hash' - name: 'container-001' - paths: [ - '/myPartitionKey' - ] - throughput: 600 - uniqueKeyPolicyKeys: [ - { - paths: [ - '/firstName' - ] - } - { - paths: [ - '/lastName' - ] - } - ] - } - ] - name: 'sql-dddasql-001' - } - { - containers: [] - name: 'sql-dddasql-002' - } - { - autoscaleSettingsMaxThroughput: 1000 - containers: [ - { - analyticalStorageTtl: 0 - autoscaleSettingsMaxThroughput: 1000 - conflictResolutionPolicy: { - conflictResolutionPath: '/myCustomId' - mode: 'LastWriterWins' - } - indexingPolicy: { - automatic: true - } - kind: 'Hash' - name: 'container-003' - paths: [ - '/myPartitionKey' - ] - uniqueKeyPolicyKeys: [ - { - paths: [ - '/firstName' - ] - } - { - paths: [ - '/lastName' - ] - } - ] - } - ] - name: 'sql-dddasql-003' + failoverPriority: 0 + isZoneRedundant: false + locationName: '' } ] - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' + name: 'user-mi' + // Non-required parameters + location: '' + managedIdentities: { + userAssignedResourceIds: [ + '' + ] } } } @@ -1259,34 +2262,13 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: "failoverPriority": 0, "isZoneRedundant": false, "locationName": "" - }, - { - "failoverPriority": 1, - "isZoneRedundant": false, - "locationName": "" } ] }, "name": { - "value": "dddasql001" + "value": "user-mi" }, // Non-required parameters - "diagnosticSettings": { - "value": [ - { - "eventHubAuthorizationRuleResourceId": "", - "eventHubName": "", - "metricCategories": [ - { - "category": "AllMetrics" - } - ], - "name": "customSetting", - "storageAccountResourceId": "", - "workspaceResourceId": "" - } - ] - }, "location": { "value": "" }, @@ -1296,131 +2278,6 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: "" ] } - }, - "privateEndpoints": { - "value": [ - { - "privateDnsZoneResourceIds": [ - "" - ], - "service": "Sql", - "subnetResourceId": "", - "tags": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } - }, - { - "privateDnsZoneResourceIds": [ - "" - ], - "service": "Sql", - "subnetResourceId": "" - } - ] - }, - "roleAssignments": { - "value": [ - { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "Owner" - }, - { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" - }, - { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "" - } - ] - }, - "sqlDatabases": { - "value": [ - { - "containers": [ - { - "analyticalStorageTtl": 0, - "conflictResolutionPolicy": { - "conflictResolutionPath": "/myCustomId", - "mode": "LastWriterWins" - }, - "defaultTtl": 1000, - "indexingPolicy": { - "automatic": true - }, - "kind": "Hash", - "name": "container-001", - "paths": [ - "/myPartitionKey" - ], - "throughput": 600, - "uniqueKeyPolicyKeys": [ - { - "paths": [ - "/firstName" - ] - }, - { - "paths": [ - "/lastName" - ] - } - ] - } - ], - "name": "sql-dddasql-001" - }, - { - "containers": [], - "name": "sql-dddasql-002" - }, - { - "autoscaleSettingsMaxThroughput": 1000, - "containers": [ - { - "analyticalStorageTtl": 0, - "autoscaleSettingsMaxThroughput": 1000, - "conflictResolutionPolicy": { - "conflictResolutionPath": "/myCustomId", - "mode": "LastWriterWins" - }, - "indexingPolicy": { - "automatic": true - }, - "kind": "Hash", - "name": "container-003", - "paths": [ - "/myPartitionKey" - ], - "uniqueKeyPolicyKeys": [ - { - "paths": [ - "/firstName" - ] - }, - { - "paths": [ - "/lastName" - ] - } - ] - } - ], - "name": "sql-dddasql-003" - } - ] - }, - "tags": { - "value": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } } } } @@ -1429,7 +2286,7 @@ module databaseAccount 'br/public:avm/res/document-db/database-account:

-### Example 6: _WAF-aligned_ +### Example 14: _WAF-aligned_ This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework. @@ -1440,7 +2297,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dddawaf' + name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddawaf' params: { // Required parameters locations: [ @@ -1639,6 +2496,70 @@ module databaseAccount 'br/public:avm/res/document-db/database-account:

+### Example 15: _Using zone redundant regions_ + +This instance deploys the module enabling multiple zone redundant in multiple regions. + + +

+ +via Bicep module + +```bicep +module databaseAccount 'br/public:avm/res/document-db/database-account:' = { + name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddazr' + params: { + // Required parameters + locations: [ + { + failoverPriority: 0 + isZoneRedundant: true + locationName: '' + } + ] + name: 'zone-redundant' + // Non-required parameters + location: '' + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "locations": { + "value": [ + { + "failoverPriority": 0, + "isZoneRedundant": true, + "locationName": "" + } + ] + }, + "name": { + "value": "zone-redundant" + }, + // Non-required parameters + "location": { + "value": "" + } + } +} +``` + +
+

+ ## Parameters @@ -1653,28 +2574,30 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: | Parameter | Type | Description | | :-- | :-- | :-- | -| [`automaticFailover`](#parameter-automaticfailover) | bool | Enable automatic failover for regions. | -| [`backupIntervalInMinutes`](#parameter-backupintervalinminutes) | int | An integer representing the interval in minutes between two backups. Only applies to periodic backup type. | -| [`backupPolicyContinuousTier`](#parameter-backuppolicycontinuoustier) | string | Configuration values for continuous mode backup. | -| [`backupPolicyType`](#parameter-backuppolicytype) | string | Describes the mode of backups. | -| [`backupRetentionIntervalInHours`](#parameter-backupretentionintervalinhours) | int | An integer representing the time (in hours) that each backup is retained. Only applies to periodic backup type. | -| [`backupStorageRedundancy`](#parameter-backupstorageredundancy) | string | Enum to indicate type of backup residency. Only applies to periodic backup type. | +| [`automaticFailover`](#parameter-automaticfailover) | bool | Default to true. Enable automatic failover for regions. | +| [`backupIntervalInMinutes`](#parameter-backupintervalinminutes) | int | Default to 240. An integer representing the interval in minutes between two backups. Only applies to periodic backup type. | +| [`backupPolicyContinuousTier`](#parameter-backuppolicycontinuoustier) | string | Default to Continuous30Days. Configuration values for continuous mode backup. | +| [`backupPolicyType`](#parameter-backuppolicytype) | string | Default to Continuous. Describes the mode of backups. | +| [`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 | The offer type for the Cosmos DB database account. | -| [`defaultConsistencyLevel`](#parameter-defaultconsistencylevel) | string | The default consistency level of the Cosmos DB account. | +| [`databaseAccountOfferType`](#parameter-databaseaccountoffertype) | string | Default to Standard. The offer type for the 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. | -| [`enableFreeTier`](#parameter-enablefreetier) | bool | Flag to indicate whether Free Tier is enabled. | +| [`disableLocalAuth`](#parameter-disablelocalauth) | bool | Default to false. Opt-out of local authentication and ensure only MSI and AAD can be used exclusively for authentication. | +| [`enableAnalyticalStorage`](#parameter-enableanalyticalstorage) | bool | Default to false. Flag to indicate whether to enable storage analytics. | +| [`enableFreeTier`](#parameter-enablefreetier) | bool | Default to false. Flag to indicate whether Free Tier is enabled. | | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`gremlinDatabases`](#parameter-gremlindatabases) | array | Gremlin Databases configurations. | -| [`location`](#parameter-location) | string | Location for all resources. | +| [`location`](#parameter-location) | string | Default to current resource group scope location. 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. | -| [`maxIntervalInSeconds`](#parameter-maxintervalinseconds) | int | Max lag time (minutes). Required for BoundedStaleness. Valid ranges, Single Region: 5 to 84600. Multi Region: 300 to 86400. | -| [`maxStalenessPrefix`](#parameter-maxstalenessprefix) | int | Max stale requests. Required for BoundedStaleness. Valid ranges, Single Region: 10 to 1000000. Multi Region: 100000 to 1000000. | +| [`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. | | [`mongodbDatabases`](#parameter-mongodbdatabases) | array | MongoDB Databases configurations. | | [`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'. | -| [`serverVersion`](#parameter-serverversion) | string | Specifies the MongoDB server version to use. | +| [`serverVersion`](#parameter-serverversion) | string | Default to 4.2. Specifies the MongoDB server version to use. | | [`sqlDatabases`](#parameter-sqldatabases) | array | SQL Databases configurations. | | [`tags`](#parameter-tags) | object | Tags of the Database Account resource. | @@ -1694,7 +2617,7 @@ Name of the Database Account. ### Parameter: `automaticFailover` -Enable automatic failover for regions. +Default to true. Enable automatic failover for regions. - Required: No - Type: bool @@ -1702,7 +2625,7 @@ Enable automatic failover for regions. ### Parameter: `backupIntervalInMinutes` -An integer representing the interval in minutes between two backups. Only applies to periodic backup type. +Default to 240. An integer representing the interval in minutes between two backups. Only applies to periodic backup type. - Required: No - Type: int @@ -1710,7 +2633,7 @@ An integer representing the interval in minutes between two backups. Only applie ### Parameter: `backupPolicyContinuousTier` -Configuration values for continuous mode backup. +Default to Continuous30Days. Configuration values for continuous mode backup. - Required: No - Type: string @@ -1725,7 +2648,7 @@ Configuration values for continuous mode backup. ### Parameter: `backupPolicyType` -Describes the mode of backups. +Default to Continuous. Describes the mode of backups. - Required: No - Type: string @@ -1740,7 +2663,7 @@ Describes the mode of backups. ### Parameter: `backupRetentionIntervalInHours` -An integer representing the time (in hours) that each backup is retained. Only applies to periodic backup type. +Default to 8. An integer representing the time (in hours) that each backup is retained. Only applies to periodic backup type. - Required: No - Type: int @@ -1748,7 +2671,7 @@ An integer representing the time (in hours) that each backup is retained. Only a ### Parameter: `backupStorageRedundancy` -Enum to indicate type of backup residency. Only applies to periodic backup type. +Default to Local. Enum to indicate type of backup residency. Only applies to periodic backup type. - Required: No - Type: string @@ -1783,7 +2706,7 @@ List of Cosmos DB capabilities for the account. ### Parameter: `databaseAccountOfferType` -The offer type for the Cosmos DB database account. +Default to Standard. The offer type for the Cosmos DB database account. - Required: No - Type: string @@ -1797,7 +2720,7 @@ The offer type for the Cosmos DB database account. ### Parameter: `defaultConsistencyLevel` -The default consistency level of the Cosmos DB account. +Default to Session. The default consistency level of the Cosmos DB account. - Required: No - Type: string @@ -1959,9 +2882,25 @@ Resource ID of the diagnostic log analytics workspace. For security reasons, it - Required: No - Type: string +### Parameter: `disableLocalAuth` + +Default to false. Opt-out of local authentication and ensure only MSI and AAD can be used exclusively for authentication. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `enableAnalyticalStorage` + +Default to false. Flag to indicate whether to enable storage analytics. + +- Required: No +- Type: bool +- Default: `False` + ### Parameter: `enableFreeTier` -Flag to indicate whether Free Tier is enabled. +Default to false. Flag to indicate whether Free Tier is enabled. - Required: No - Type: bool @@ -1985,7 +2924,7 @@ Gremlin Databases configurations. ### Parameter: `location` -Location for all resources. +Default to current resource group scope location. Location for all resources. - Required: No - Type: string @@ -2057,7 +2996,7 @@ The resource ID(s) to assign to the resource. ### Parameter: `maxIntervalInSeconds` -Max lag time (minutes). Required for BoundedStaleness. Valid ranges, Single Region: 5 to 84600. Multi Region: 300 to 86400. +Default to 300. Max lag time (minutes). Required for BoundedStaleness. Valid ranges, Single Region: 5 to 84600. Multi Region: 300 to 86400. - Required: No - Type: int @@ -2065,7 +3004,7 @@ Max lag time (minutes). Required for BoundedStaleness. Valid ranges, Single Regi ### Parameter: `maxStalenessPrefix` -Max stale requests. Required for BoundedStaleness. Valid ranges, Single Region: 10 to 1000000. Multi Region: 100000 to 1000000. +Default to 100000. Max stale requests. Required for BoundedStaleness. Valid ranges, Single Region: 10 to 1000000. Multi Region: 100000 to 1000000. - Required: No - Type: int @@ -2497,7 +3436,7 @@ The principal type of the assigned principal ID. ### Parameter: `serverVersion` -Specifies the MongoDB server version to use. +Default to 4.2. Specifies the MongoDB server version to use. - Required: No - Type: string diff --git a/avm/res/document-db/database-account/main.bicep b/avm/res/document-db/database-account/main.bicep index 7adb1ac997..6e5e62b83c 100644 --- a/avm/res/document-db/database-account/main.bicep +++ b/avm/res/document-db/database-account/main.bicep @@ -5,7 +5,7 @@ metadata owner = 'Azure/module-maintainers' @description('Required. Name of the Database Account.') param name string -@description('Optional. Location for all resources.') +@description('Optional. Default to current resource group scope location. Location for all resources.') param location string = resourceGroup().location @description('Optional. Tags of the Database Account resource.') @@ -14,14 +14,14 @@ param tags object? @description('Optional. The managed identity definition for this resource.') param managedIdentities managedIdentitiesType -@description('Optional. The offer type for the Cosmos DB database account.') +@description('Optional. Default to Standard. The offer type for the Cosmos DB database account.') @allowed([ 'Standard' ]) param databaseAccountOfferType string = 'Standard' @description('Required. Locations enabled for the Cosmos DB account.') -param locations array +param locations failoverLocations[] @allowed([ 'Eventual' @@ -30,26 +30,32 @@ param locations array 'BoundedStaleness' 'Strong' ]) -@description('Optional. The default consistency level of the Cosmos DB account.') +@description('Optional. Default to Session. The default consistency level of the Cosmos DB account.') param defaultConsistencyLevel string = 'Session' -@description('Optional. Enable automatic failover for regions.') +@description('Optional. Default to false. Opt-out of local authentication and ensure only MSI and AAD can be used exclusively for authentication.') +param disableLocalAuth bool = false + +@description('Optional. Default to false. Flag to indicate whether to enable storage analytics.') +param enableAnalyticalStorage bool = false + +@description('Optional. Default to true. Enable automatic failover for regions.') param automaticFailover bool = true -@description('Optional. Flag to indicate whether Free Tier is enabled.') +@description('Optional. Default to false. Flag to indicate whether Free Tier is enabled.') param enableFreeTier bool = false -@minValue(10) +@minValue(1) @maxValue(2147483647) -@description('Optional. Max stale requests. Required for BoundedStaleness. Valid ranges, Single Region: 10 to 1000000. Multi Region: 100000 to 1000000.') +@description('Optional. Default to 100000. Max stale requests. Required for BoundedStaleness. Valid ranges, Single Region: 10 to 1000000. Multi Region: 100000 to 1000000.') param maxStalenessPrefix int = 100000 @minValue(5) @maxValue(86400) -@description('Optional. Max lag time (minutes). Required for BoundedStaleness. Valid ranges, Single Region: 5 to 84600. Multi Region: 300 to 86400.') +@description('Optional. Default to 300. Max lag time (minutes). Required for BoundedStaleness. Valid ranges, Single Region: 5 to 84600. Multi Region: 300 to 86400.') param maxIntervalInSeconds int = 300 -@description('Optional. Specifies the MongoDB server version to use.') +@description('Optional. Default to 4.2. Specifies the MongoDB server version to use.') @allowed([ '3.2' '3.6' @@ -59,7 +65,7 @@ param maxIntervalInSeconds int = 300 param serverVersion string = '4.2' @description('Optional. SQL Databases configurations.') -param sqlDatabases array = [] +param sqlDatabases sqlDatabase[] = [] @description('Optional. MongoDB Databases configurations.') param mongodbDatabases array = [] @@ -88,30 +94,30 @@ param diagnosticSettings diagnosticSettingType 'EnableServerless' ]) @description('Optional. List of Cosmos DB capabilities for the account.') -param capabilitiesToAdd array = [] +param capabilitiesToAdd string[] = [] @allowed([ 'Periodic' 'Continuous' ]) -@description('Optional. Describes the mode of backups.') +@description('Optional. Default to Continuous. Describes the mode of backups.') param backupPolicyType string = 'Continuous' @allowed([ 'Continuous30Days' 'Continuous7Days' ]) -@description('Optional. Configuration values for continuous mode backup.') +@description('Optional. Default to Continuous30Days. Configuration values for continuous mode backup.') param backupPolicyContinuousTier string = 'Continuous30Days' @minValue(60) @maxValue(1440) -@description('Optional. An integer representing the interval in minutes between two backups. Only applies to periodic backup type.') +@description('Optional. Default to 240. An integer representing the interval in minutes between two backups. Only applies to periodic backup type.') param backupIntervalInMinutes int = 240 @minValue(2) @maxValue(720) -@description('Optional. An integer representing the time (in hours) that each backup is retained. Only applies to periodic backup type.') +@description('Optional. Default to 8. An integer representing the time (in hours) that each backup is retained. Only applies to periodic backup type.') param backupRetentionIntervalInHours int = 8 @allowed([ @@ -119,7 +125,7 @@ param backupRetentionIntervalInHours int = 8 'Local' 'Zone' ]) -@description('Optional. Enum to indicate type of backup residency. Only applies to periodic backup type.') +@description('Optional. Default to Local. Enum to indicate type of backup residency. Only applies to periodic backup type.') param backupStorageRedundancy string = 'Local' @description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') @@ -187,9 +193,11 @@ var databaseAccount_properties = union({ capabilities: capabilities enableFreeTier: enableFreeTier backupPolicy: backupPolicy + enableAutomaticFailover: automaticFailover + enableAnalyticalStorage: enableAnalyticalStorage } : {}), (!empty(sqlDatabases) ? { // SQLDB properties - enableAutomaticFailover: automaticFailover + disableLocalAuth: disableLocalAuth } : {}), (!empty(mongodbDatabases) ? { // MongoDb properties apiProperties: { @@ -286,10 +294,10 @@ resource databaseAccount_roleAssignments 'Microsoft.Authorization/roleAssignment module databaseAccount_sqlDatabases 'sql-database/main.bicep' = [for sqlDatabase in sqlDatabases: { name: '${uniqueString(deployment().name, location)}-sqldb-${sqlDatabase.name}' params: { - databaseAccountName: databaseAccount.name name: sqlDatabase.name - containers: contains(sqlDatabase, 'containers') ? sqlDatabase.containers : [] - throughput: contains(sqlDatabase, 'throughput') ? sqlDatabase.throughput : 400 + containers: sqlDatabase.?containers + throughput: sqlDatabase.?throughput + databaseAccountName: databaseAccount.name autoscaleSettingsMaxThroughput: sqlDatabase.?autoscaleSettingsMaxThroughput } }] @@ -532,3 +540,77 @@ type diagnosticSettingType = { @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') marketplacePartnerResourceId: string? }[]? + +type failoverLocations = { + @description('Required. The failover priority of the region. A failover priority of 0 indicates a write region. The maximum value for a failover priority = (total number of regions - 1). Failover priority values must be unique for each of the regions in which the database account exists.') + failoverPriority: int + + @description('Required. Flag to indicate whether or not this region is an AvailabilityZone region') + isZoneRedundant: bool + + @description('Required. The name of the region.') + locationName: string +} + +type sqlDatabase = { + @description('Required. Name of the SQL database .') + name: string + + @description('Optional. Default to 400. Request units per second. Will be ignored if autoscaleSettingsMaxThroughput is used.') + throughput: int? + + @description('Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to null, then autoscale will be disabled.') + autoscaleSettingsMaxThroughput: int? + + @description('Optional. Array of containers to deploy in the SQL database.') + containers: sqlDatabaseContainer[]? +} + +type sqlDatabaseContainer = { + @description('Required. Name of the container.') + name: string + + @maxLength(3) + @minLength(1) + @description('Required. List of paths using which data within the container can be partitioned. For kind=MultiHash it can be up to 3. For anything else it needs to be exactly 1.') + paths: string[] + + @description('Optional. Default to 0. Indicates how long data should be retained in the analytical store, for a container. Analytical store is enabled when ATTL is set with a value other than 0. If the value is set to -1, the analytical store retains all historical data, irrespective of the retention of the data in the transactional store.') + analyticalStorageTtl: int? + + @maxValue(1000000) + @description('Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to null, then autoscale will be disabled.') + autoscaleSettingsMaxThroughput: int? + + @description('Optional. The conflict resolution policy for the container. Conflicts and conflict resolution policies are applicable if the Azure Cosmos DB account is configured with multiple write regions.') + conflictResolutionPolicy: { + @description('Required if mode=LastWriterWins. The conflict resolution path in the case of LastWriterWins mode.') + conflictResolutionPath: string? + + @description('Required if mode=Custom. The procedure to resolve conflicts in the case of custom mode.') + conflictResolutionProcedure: string? + + @description('Required. Indicates the conflict resolution mode.') + mode: ('Custom' | 'LastWriterWins') + }? + + @maxValue(2147483647) + @minValue(-1) + @description('Optional. Default to -1. Default time to live (in seconds). With Time to Live or TTL, Azure Cosmos DB provides the ability to delete items automatically from a container after a certain time period. If the value is set to "-1", it is equal to infinity, and items don\'t expire by default.') + defaultTtl: int? + + @description('Optional. Indexing policy of the container.') + indexingPolicy: object? + + @description('Optional. Default to Hash. Indicates the kind of algorithm used for partitioning.') + kind: ('Hash' | 'MultiHash' | 'Range')? + + @description('Optional. Default to 400. Request Units per second. Will be ignored if autoscaleSettingsMaxThroughput is used.') + throughput: int? + + @description('Optional. The unique key policy configuration containing a list of unique keys that enforces uniqueness constraint on documents in the collection in the Azure Cosmos DB service.') + uniqueKeyPolicyKeys: { + @description('List of paths must be unique for each document in the Azure Cosmos DB service') + paths: string[] + }[]? +} diff --git a/avm/res/document-db/database-account/main.json b/avm/res/document-db/database-account/main.json index 3a3f8d75a5..fbe677ed99 100644 --- a/avm/res/document-db/database-account/main.json +++ b/avm/res/document-db/database-account/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "6178968809986230954" + "templateHash": "8733005894926174924" }, "name": "DocumentDB Database Accounts", "description": "This module deploys a DocumentDB Database Account.", @@ -428,6 +428,190 @@ } }, "nullable": true + }, + "failoverLocations": { + "type": "object", + "properties": { + "failoverPriority": { + "type": "int", + "metadata": { + "description": "Required. The failover priority of the region. A failover priority of 0 indicates a write region. The maximum value for a failover priority = (total number of regions - 1). Failover priority values must be unique for each of the regions in which the database account exists." + } + }, + "isZoneRedundant": { + "type": "bool", + "metadata": { + "description": "Required. Flag to indicate whether or not this region is an AvailabilityZone region" + } + }, + "locationName": { + "type": "string", + "metadata": { + "description": "Required. The name of the region." + } + } + } + }, + "sqlDatabase": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the SQL database ." + } + }, + "throughput": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Default to 400. Request units per second. Will be ignored if autoscaleSettingsMaxThroughput is used." + } + }, + "autoscaleSettingsMaxThroughput": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to null, then autoscale will be disabled." + } + }, + "containers": { + "type": "array", + "items": { + "$ref": "#/definitions/sqlDatabaseContainer" + }, + "nullable": true, + "metadata": { + "description": "Optional. Array of containers to deploy in the SQL database." + } + } + } + }, + "sqlDatabaseContainer": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the container." + } + }, + "paths": { + "type": "array", + "items": { + "type": "string" + }, + "minLength": 1, + "maxLength": 3, + "metadata": { + "description": "Required. List of paths using which data within the container can be partitioned. For kind=MultiHash it can be up to 3. For anything else it needs to be exactly 1." + } + }, + "analyticalStorageTtl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Default to 0. Indicates how long data should be retained in the analytical store, for a container. Analytical store is enabled when ATTL is set with a value other than 0. If the value is set to -1, the analytical store retains all historical data, irrespective of the retention of the data in the transactional store." + } + }, + "autoscaleSettingsMaxThroughput": { + "type": "int", + "nullable": true, + "maxValue": 1000000, + "metadata": { + "description": "Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to null, then autoscale will be disabled." + } + }, + "conflictResolutionPolicy": { + "type": "object", + "properties": { + "conflictResolutionPath": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Required if mode=LastWriterWins. The conflict resolution path in the case of LastWriterWins mode." + } + }, + "conflictResolutionProcedure": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Required if mode=Custom. The procedure to resolve conflicts in the case of custom mode." + } + }, + "mode": { + "type": "string", + "allowedValues": [ + "Custom", + "LastWriterWins" + ], + "metadata": { + "description": "Required. Indicates the conflict resolution mode." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The conflict resolution policy for the container. Conflicts and conflict resolution policies are applicable if the Azure Cosmos DB account is configured with multiple write regions." + } + }, + "defaultTtl": { + "type": "int", + "nullable": true, + "minValue": -1, + "maxValue": 2147483647, + "metadata": { + "description": "Optional. Default to -1. Default time to live (in seconds). With Time to Live or TTL, Azure Cosmos DB provides the ability to delete items automatically from a container after a certain time period. If the value is set to \"-1\", it is equal to infinity, and items don't expire by default." + } + }, + "indexingPolicy": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Indexing policy of the container." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "Hash", + "MultiHash", + "Range" + ], + "nullable": true, + "metadata": { + "description": "Optional. Default to Hash. Indicates the kind of algorithm used for partitioning." + } + }, + "throughput": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Default to 400. Request Units per second. Will be ignored if autoscaleSettingsMaxThroughput is used." + } + }, + "uniqueKeyPolicyKeys": { + "type": "array", + "items": { + "type": "object", + "properties": { + "paths": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "List of paths must be unique for each document in the Azure Cosmos DB service" + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The unique key policy configuration containing a list of unique keys that enforces uniqueness constraint on documents in the collection in the Azure Cosmos DB service." + } + } + } } }, "parameters": { @@ -441,7 +625,7 @@ "type": "string", "defaultValue": "[resourceGroup().location]", "metadata": { - "description": "Optional. Location for all resources." + "description": "Optional. Default to current resource group scope location. Location for all resources." } }, "tags": { @@ -464,11 +648,14 @@ "Standard" ], "metadata": { - "description": "Optional. The offer type for the Cosmos DB database account." + "description": "Optional. Default to Standard. The offer type for the Cosmos DB database account." } }, "locations": { "type": "array", + "items": { + "$ref": "#/definitions/failoverLocations" + }, "metadata": { "description": "Required. Locations enabled for the Cosmos DB account." } @@ -484,30 +671,44 @@ "Strong" ], "metadata": { - "description": "Optional. The default consistency level of the Cosmos DB account." + "description": "Optional. Default to Session. The default consistency level of the Cosmos DB account." + } + }, + "disableLocalAuth": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Default to false. Opt-out of local authentication and ensure only MSI and AAD can be used exclusively for authentication." + } + }, + "enableAnalyticalStorage": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Default to false. Flag to indicate whether to enable storage analytics." } }, "automaticFailover": { "type": "bool", "defaultValue": true, "metadata": { - "description": "Optional. Enable automatic failover for regions." + "description": "Optional. Default to true. Enable automatic failover for regions." } }, "enableFreeTier": { "type": "bool", "defaultValue": false, "metadata": { - "description": "Optional. Flag to indicate whether Free Tier is enabled." + "description": "Optional. Default to false. Flag to indicate whether Free Tier is enabled." } }, "maxStalenessPrefix": { "type": "int", "defaultValue": 100000, - "minValue": 10, + "minValue": 1, "maxValue": 2147483647, "metadata": { - "description": "Optional. Max stale requests. Required for BoundedStaleness. Valid ranges, Single Region: 10 to 1000000. Multi Region: 100000 to 1000000." + "description": "Optional. Default to 100000. Max stale requests. Required for BoundedStaleness. Valid ranges, Single Region: 10 to 1000000. Multi Region: 100000 to 1000000." } }, "maxIntervalInSeconds": { @@ -516,7 +717,7 @@ "minValue": 5, "maxValue": 86400, "metadata": { - "description": "Optional. Max lag time (minutes). Required for BoundedStaleness. Valid ranges, Single Region: 5 to 84600. Multi Region: 300 to 86400." + "description": "Optional. Default to 300. Max lag time (minutes). Required for BoundedStaleness. Valid ranges, Single Region: 5 to 84600. Multi Region: 300 to 86400." } }, "serverVersion": { @@ -529,11 +730,14 @@ "4.2" ], "metadata": { - "description": "Optional. Specifies the MongoDB server version to use." + "description": "Optional. Default to 4.2. Specifies the MongoDB server version to use." } }, "sqlDatabases": { "type": "array", + "items": { + "$ref": "#/definitions/sqlDatabase" + }, "defaultValue": [], "metadata": { "description": "Optional. SQL Databases configurations." @@ -580,6 +784,9 @@ }, "capabilitiesToAdd": { "type": "array", + "items": { + "type": "string" + }, "defaultValue": [], "allowedValues": [ "EnableCassandra", @@ -601,7 +808,7 @@ "Continuous" ], "metadata": { - "description": "Optional. Describes the mode of backups." + "description": "Optional. Default to Continuous. Describes the mode of backups." } }, "backupPolicyContinuousTier": { @@ -612,7 +819,7 @@ "Continuous7Days" ], "metadata": { - "description": "Optional. Configuration values for continuous mode backup." + "description": "Optional. Default to Continuous30Days. Configuration values for continuous mode backup." } }, "backupIntervalInMinutes": { @@ -621,7 +828,7 @@ "minValue": 60, "maxValue": 1440, "metadata": { - "description": "Optional. An integer representing the interval in minutes between two backups. Only applies to periodic backup type." + "description": "Optional. Default to 240. An integer representing the interval in minutes between two backups. Only applies to periodic backup type." } }, "backupRetentionIntervalInHours": { @@ -630,7 +837,7 @@ "minValue": 2, "maxValue": 720, "metadata": { - "description": "Optional. An integer representing the time (in hours) that each backup is retained. Only applies to periodic backup type." + "description": "Optional. Default to 8. An integer representing the time (in hours) that each backup is retained. Only applies to periodic backup type." } }, "backupStorageRedundancy": { @@ -642,7 +849,7 @@ "Zone" ], "metadata": { - "description": "Optional. Enum to indicate type of backup residency. Only applies to periodic backup type." + "description": "Optional. Default to Local. Enum to indicate type of backup residency. Only applies to periodic backup type." } }, "privateEndpoints": { @@ -694,7 +901,7 @@ }, "kind": "[if(or(not(empty(parameters('sqlDatabases'))), not(empty(parameters('gremlinDatabases')))), 'GlobalDocumentDB', if(not(empty(parameters('mongodbDatabases'))), 'MongoDB', 'Parse'))]", "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'))))]", - "databaseAccount_properties": "[union(createObject('databaseAccountOfferType', parameters('databaseAccountOfferType')), if(or(or(not(empty(parameters('sqlDatabases'))), not(empty(parameters('mongodbDatabases')))), not(empty(parameters('gremlinDatabases')))), createObject('consistencyPolicy', variables('consistencyPolicy')[parameters('defaultConsistencyLevel')], 'locations', variables('databaseAccount_locations'), 'capabilities', variables('capabilities'), 'enableFreeTier', parameters('enableFreeTier'), 'backupPolicy', variables('backupPolicy')), createObject()), if(not(empty(parameters('sqlDatabases'))), createObject('enableAutomaticFailover', parameters('automaticFailover')), createObject()), if(not(empty(parameters('mongodbDatabases'))), createObject('apiProperties', createObject('serverVersion', parameters('serverVersion'))), createObject()))]", + "databaseAccount_properties": "[union(createObject('databaseAccountOfferType', parameters('databaseAccountOfferType')), if(or(or(not(empty(parameters('sqlDatabases'))), not(empty(parameters('mongodbDatabases')))), not(empty(parameters('gremlinDatabases')))), createObject('consistencyPolicy', variables('consistencyPolicy')[parameters('defaultConsistencyLevel')], 'locations', variables('databaseAccount_locations'), 'capabilities', variables('capabilities'), 'enableFreeTier', parameters('enableFreeTier'), 'backupPolicy', variables('backupPolicy'), 'enableAutomaticFailover', parameters('automaticFailover'), 'enableAnalyticalStorage', parameters('enableAnalyticalStorage')), createObject()), if(not(empty(parameters('sqlDatabases'))), createObject('disableLocalAuth', parameters('disableLocalAuth')), 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')]", @@ -830,14 +1037,18 @@ }, "mode": "Incremental", "parameters": { - "databaseAccountName": { - "value": "[parameters('name')]" - }, "name": { "value": "[parameters('sqlDatabases')[copyIndex()].name]" }, - "containers": "[if(contains(parameters('sqlDatabases')[copyIndex()], 'containers'), createObject('value', parameters('sqlDatabases')[copyIndex()].containers), createObject('value', createArray()))]", - "throughput": "[if(contains(parameters('sqlDatabases')[copyIndex()], 'throughput'), createObject('value', parameters('sqlDatabases')[copyIndex()].throughput), createObject('value', 400))]", + "containers": { + "value": "[tryGet(parameters('sqlDatabases')[copyIndex()], 'containers')]" + }, + "throughput": { + "value": "[tryGet(parameters('sqlDatabases')[copyIndex()], 'throughput')]" + }, + "databaseAccountName": { + "value": "[parameters('name')]" + }, "autoscaleSettingsMaxThroughput": { "value": "[tryGet(parameters('sqlDatabases')[copyIndex()], 'autoscaleSettingsMaxThroughput')]" } @@ -850,7 +1061,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "3371007626132936503" + "templateHash": "1307928694299767068" }, "name": "DocumentDB Database Account SQL Databases", "description": "This module deploys a SQL Database in a CosmosDB Account.", @@ -871,6 +1082,9 @@ }, "containers": { "type": "array", + "items": { + "type": "object" + }, "defaultValue": [], "metadata": { "description": "Optional. Array of containers to deploy in the SQL database." @@ -878,16 +1092,16 @@ }, "throughput": { "type": "int", - "defaultValue": 400, + "nullable": true, "metadata": { - "description": "Optional. Request units per second. Will be set to null if autoscaleSettingsMaxThroughput is used." + "description": "Optional. Request units per second. Will be ignored if autoscaleSettingsMaxThroughput is used." } }, "autoscaleSettingsMaxThroughput": { "type": "int", "nullable": true, "metadata": { - "description": "Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to -1, then the property will be set to null and autoscale will be disabled." + "description": "Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to null, then autoscale will be disabled." } }, "tags": { @@ -943,19 +1157,31 @@ "name": { "value": "[parameters('containers')[copyIndex()].name]" }, - "analyticalStorageTtl": "[if(contains(parameters('containers')[copyIndex()], 'analyticalStorageTtl'), createObject('value', parameters('containers')[copyIndex()].analyticalStorageTtl), createObject('value', 0))]", + "analyticalStorageTtl": { + "value": "[tryGet(parameters('containers')[copyIndex()], 'analyticalStorageTtl')]" + }, "autoscaleSettingsMaxThroughput": { "value": "[tryGet(parameters('containers')[copyIndex()], 'autoscaleSettingsMaxThroughput')]" }, - "conflictResolutionPolicy": "[if(contains(parameters('containers')[copyIndex()], 'conflictResolutionPolicy'), createObject('value', parameters('containers')[copyIndex()].conflictResolutionPolicy), createObject('value', createObject()))]", + "conflictResolutionPolicy": { + "value": "[tryGet(parameters('containers')[copyIndex()], 'conflictResolutionPolicy')]" + }, "defaultTtl": { "value": "[tryGet(parameters('containers')[copyIndex()], 'defaultTtl')]" }, - "indexingPolicy": "[if(contains(parameters('containers')[copyIndex()], 'indexingPolicy'), createObject('value', parameters('containers')[copyIndex()].indexingPolicy), createObject('value', createObject()))]", - "kind": "[if(contains(parameters('containers')[copyIndex()], 'kind'), createObject('value', parameters('containers')[copyIndex()].kind), createObject('value', 'Hash'))]", - "paths": "[if(contains(parameters('containers')[copyIndex()], 'paths'), createObject('value', parameters('containers')[copyIndex()].paths), createObject('value', createArray()))]", - "throughput": "[if(contains(parameters('containers')[copyIndex()], 'throughput'), createObject('value', parameters('containers')[copyIndex()].throughput), createObject('value', 400))]", - "uniqueKeyPolicyKeys": "[if(contains(parameters('containers')[copyIndex()], 'uniqueKeyPolicyKeys'), createObject('value', parameters('containers')[copyIndex()].uniqueKeyPolicyKeys), createObject('value', createArray()))]" + "indexingPolicy": { + "value": "[tryGet(parameters('containers')[copyIndex()], 'indexingPolicy')]" + }, + "kind": { + "value": "[tryGet(parameters('containers')[copyIndex()], 'kind')]" + }, + "paths": { + "value": "[tryGet(parameters('containers')[copyIndex()], 'paths')]" + }, + "throughput": "[if(and(or(not(equals(parameters('throughput'), null())), not(equals(parameters('autoscaleSettingsMaxThroughput'), null()))), equals(tryGet(parameters('containers')[copyIndex()], 'throughput'), null())), createObject('value', -1), createObject('value', tryGet(parameters('containers')[copyIndex()], 'throughput')))]", + "uniqueKeyPolicyKeys": { + "value": "[tryGet(parameters('containers')[copyIndex()], 'uniqueKeyPolicyKeys')]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -965,7 +1191,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "15407611441750959399" + "templateHash": "8159752253553558916" }, "name": "DocumentDB Database Account SQL Database Containers", "description": "This module deploys a SQL Database Container in a CosmosDB Account.", @@ -994,7 +1220,7 @@ "type": "int", "defaultValue": 0, "metadata": { - "description": "Optional. Indicates how long data should be retained in the analytical store, for a container. Analytical store is enabled when ATTL is set with a value other than 0. If the value is set to -1, the analytical store retains all historical data, irrespective of the retention of the data in the transactional store." + "description": "Optional. Default to 0. Indicates how long data should be retained in the analytical store, for a container. Analytical store is enabled when ATTL is set with a value other than 0. If the value is set to -1, the analytical store retains all historical data, irrespective of the retention of the data in the transactional store." } }, "conflictResolutionPolicy": { @@ -1010,14 +1236,14 @@ "minValue": -1, "maxValue": 2147483647, "metadata": { - "description": "Optional. Default time to live (in seconds). With Time to Live or TTL, Azure Cosmos DB provides the ability to delete items automatically from a container after a certain time period. If the value is set to \"-1\", it is equal to infinity, and items don't expire by default." + "description": "Optional. Default to -1. Default time to live (in seconds). With Time to Live or TTL, Azure Cosmos DB provides the ability to delete items automatically from a container after a certain time period. If the value is set to \"-1\", it is equal to infinity, and items don't expire by default." } }, "throughput": { "type": "int", "defaultValue": 400, "metadata": { - "description": "Optional. Request Units per second. Will be set to null if autoscaleSettingsMaxThroughput is used." + "description": "Optional. Default to 400. Request Units per second. Will be ignored if autoscaleSettingsMaxThroughput is used." } }, "autoscaleSettingsMaxThroughput": { @@ -1025,7 +1251,7 @@ "nullable": true, "maxValue": 1000000, "metadata": { - "description": "Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to -1, then the property will be set to null and autoscale will be disabled." + "description": "Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to null, then autoscale will be disabled." } }, "tags": { @@ -1037,9 +1263,13 @@ }, "paths": { "type": "array", - "defaultValue": [], + "items": { + "type": "string" + }, + "minLength": 1, + "maxLength": 3, "metadata": { - "description": "Optional. List of paths using which data within the container can be partitioned." + "description": "Required. List of paths using which data within the container can be partitioned. For kind=MultiHash it can be up to 3. For anything else it needs to be exactly 1." } }, "indexingPolicy": { @@ -1065,7 +1295,7 @@ "Range" ], "metadata": { - "description": "Optional. Indicates the kind of algorithm used for partitioning." + "description": "Optional. Default to Hash. Indicates the kind of algorithm used for partitioning." } } }, @@ -1098,12 +1328,19 @@ "id": "[parameters('name')]", "indexingPolicy": "[if(not(empty(parameters('indexingPolicy'))), parameters('indexingPolicy'), null())]", "partitionKey": { - "paths": "[parameters('paths')]", - "kind": "[parameters('kind')]" + "copy": [ + { + "name": "paths", + "count": "[length(parameters('paths'))]", + "input": "[if(startsWith(parameters('paths')[copyIndex('paths')], '/'), parameters('paths')[copyIndex('paths')], format('/{0}', parameters('paths')[copyIndex('paths')]))]" + } + ], + "kind": "[parameters('kind')]", + "version": "[if(equals(parameters('kind'), 'MultiHash'), 2, 1)]" }, "uniqueKeyPolicy": "[if(not(empty(parameters('uniqueKeyPolicyKeys'))), createObject('uniqueKeys', parameters('uniqueKeyPolicyKeys')), null())]" }, - "options": "[if(contains(reference('databaseAccount').capabilities, createObject('name', 'EnableServerless')), null(), createObject('throughput', if(equals(parameters('autoscaleSettingsMaxThroughput'), null()), parameters('throughput'), null()), 'autoscaleSettings', if(not(equals(parameters('autoscaleSettingsMaxThroughput'), null())), createObject('maxThroughput', parameters('autoscaleSettingsMaxThroughput')), null())))]" + "options": "[if(contains(reference('databaseAccount').capabilities, createObject('name', 'EnableServerless')), null(), createObject('throughput', if(and(equals(parameters('autoscaleSettingsMaxThroughput'), null()), not(equals(parameters('throughput'), -1))), parameters('throughput'), null()), 'autoscaleSettings', if(not(equals(parameters('autoscaleSettingsMaxThroughput'), null())), createObject('maxThroughput', parameters('autoscaleSettingsMaxThroughput')), null())))]" }, "dependsOn": [ "databaseAccount::sqlDatabase" diff --git a/avm/res/document-db/database-account/sql-database/README.md b/avm/res/document-db/database-account/sql-database/README.md index efdfb6533c..354f78c0b6 100644 --- a/avm/res/document-db/database-account/sql-database/README.md +++ b/avm/res/document-db/database-account/sql-database/README.md @@ -35,10 +35,10 @@ This module deploys a SQL Database in a CosmosDB Account. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`autoscaleSettingsMaxThroughput`](#parameter-autoscalesettingsmaxthroughput) | int | Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to -1, then the property will be set to null and autoscale will be disabled. | +| [`autoscaleSettingsMaxThroughput`](#parameter-autoscalesettingsmaxthroughput) | int | Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to null, then autoscale will be disabled. | | [`containers`](#parameter-containers) | array | Array of containers to deploy in the SQL database. | | [`tags`](#parameter-tags) | object | Tags of the SQL database resource. | -| [`throughput`](#parameter-throughput) | int | Request units per second. Will be set to null if autoscaleSettingsMaxThroughput is used. | +| [`throughput`](#parameter-throughput) | int | Request units per second. Will be ignored if autoscaleSettingsMaxThroughput is used. | ### Parameter: `name` @@ -56,7 +56,7 @@ The name of the parent Database Account. Required if the template is used in a s ### Parameter: `autoscaleSettingsMaxThroughput` -Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to -1, then the property will be set to null and autoscale will be disabled. +Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to null, then autoscale will be disabled. - Required: No - Type: int @@ -78,11 +78,10 @@ Tags of the SQL database resource. ### Parameter: `throughput` -Request units per second. Will be set to null if autoscaleSettingsMaxThroughput is used. +Request units per second. Will be ignored if autoscaleSettingsMaxThroughput is used. - Required: No - Type: int -- Default: `400` ## Outputs diff --git a/avm/res/document-db/database-account/sql-database/container/README.md b/avm/res/document-db/database-account/sql-database/container/README.md index 3118bcbe86..c8227d7ff2 100644 --- a/avm/res/document-db/database-account/sql-database/container/README.md +++ b/avm/res/document-db/database-account/sql-database/container/README.md @@ -24,6 +24,7 @@ This module deploys a SQL Database Container in a CosmosDB Account. | Parameter | Type | Description | | :-- | :-- | :-- | | [`name`](#parameter-name) | string | Name of the container. | +| [`paths`](#parameter-paths) | array | List of paths using which data within the container can be partitioned. For kind=MultiHash it can be up to 3. For anything else it needs to be exactly 1. | **Conditional parameters** @@ -36,15 +37,14 @@ This module deploys a SQL Database Container in a CosmosDB Account. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`analyticalStorageTtl`](#parameter-analyticalstoragettl) | int | Indicates how long data should be retained in the analytical store, for a container. Analytical store is enabled when ATTL is set with a value other than 0. If the value is set to -1, the analytical store retains all historical data, irrespective of the retention of the data in the transactional store. | -| [`autoscaleSettingsMaxThroughput`](#parameter-autoscalesettingsmaxthroughput) | int | Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to -1, then the property will be set to null and autoscale will be disabled. | +| [`analyticalStorageTtl`](#parameter-analyticalstoragettl) | int | Default to 0. Indicates how long data should be retained in the analytical store, for a container. Analytical store is enabled when ATTL is set with a value other than 0. If the value is set to -1, the analytical store retains all historical data, irrespective of the retention of the data in the transactional store. | +| [`autoscaleSettingsMaxThroughput`](#parameter-autoscalesettingsmaxthroughput) | int | Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to null, then autoscale will be disabled. | | [`conflictResolutionPolicy`](#parameter-conflictresolutionpolicy) | object | The conflict resolution policy for the container. Conflicts and conflict resolution policies are applicable if the Azure Cosmos DB account is configured with multiple write regions. | -| [`defaultTtl`](#parameter-defaultttl) | int | Default time to live (in seconds). With Time to Live or TTL, Azure Cosmos DB provides the ability to delete items automatically from a container after a certain time period. If the value is set to "-1", it is equal to infinity, and items don't expire by default. | +| [`defaultTtl`](#parameter-defaultttl) | int | Default to -1. Default time to live (in seconds). With Time to Live or TTL, Azure Cosmos DB provides the ability to delete items automatically from a container after a certain time period. If the value is set to "-1", it is equal to infinity, and items don't expire by default. | | [`indexingPolicy`](#parameter-indexingpolicy) | object | Indexing policy of the container. | -| [`kind`](#parameter-kind) | string | Indicates the kind of algorithm used for partitioning. | -| [`paths`](#parameter-paths) | array | List of paths using which data within the container can be partitioned. | +| [`kind`](#parameter-kind) | string | Default to Hash. Indicates the kind of algorithm used for partitioning. | | [`tags`](#parameter-tags) | object | Tags of the SQL Database resource. | -| [`throughput`](#parameter-throughput) | int | Request Units per second. Will be set to null if autoscaleSettingsMaxThroughput is used. | +| [`throughput`](#parameter-throughput) | int | Default to 400. Request Units per second. Will be ignored if autoscaleSettingsMaxThroughput is used. | | [`uniqueKeyPolicyKeys`](#parameter-uniquekeypolicykeys) | array | The unique key policy configuration containing a list of unique keys that enforces uniqueness constraint on documents in the collection in the Azure Cosmos DB service. | ### Parameter: `name` @@ -54,6 +54,13 @@ Name of the container. - Required: Yes - Type: string +### Parameter: `paths` + +List of paths using which data within the container can be partitioned. For kind=MultiHash it can be up to 3. For anything else it needs to be exactly 1. + +- Required: Yes +- Type: array + ### Parameter: `databaseAccountName` The name of the parent Database Account. Required if the template is used in a standalone deployment. @@ -70,7 +77,7 @@ The name of the parent SQL Database. Required if the template is used in a stand ### Parameter: `analyticalStorageTtl` -Indicates how long data should be retained in the analytical store, for a container. Analytical store is enabled when ATTL is set with a value other than 0. If the value is set to -1, the analytical store retains all historical data, irrespective of the retention of the data in the transactional store. +Default to 0. Indicates how long data should be retained in the analytical store, for a container. Analytical store is enabled when ATTL is set with a value other than 0. If the value is set to -1, the analytical store retains all historical data, irrespective of the retention of the data in the transactional store. - Required: No - Type: int @@ -78,7 +85,7 @@ Indicates how long data should be retained in the analytical store, for a contai ### Parameter: `autoscaleSettingsMaxThroughput` -Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to -1, then the property will be set to null and autoscale will be disabled. +Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to null, then autoscale will be disabled. - Required: No - Type: int @@ -93,7 +100,7 @@ The conflict resolution policy for the container. Conflicts and conflict resolut ### Parameter: `defaultTtl` -Default time to live (in seconds). With Time to Live or TTL, Azure Cosmos DB provides the ability to delete items automatically from a container after a certain time period. If the value is set to "-1", it is equal to infinity, and items don't expire by default. +Default to -1. Default time to live (in seconds). With Time to Live or TTL, Azure Cosmos DB provides the ability to delete items automatically from a container after a certain time period. If the value is set to "-1", it is equal to infinity, and items don't expire by default. - Required: No - Type: int @@ -109,7 +116,7 @@ Indexing policy of the container. ### Parameter: `kind` -Indicates the kind of algorithm used for partitioning. +Default to Hash. Indicates the kind of algorithm used for partitioning. - Required: No - Type: string @@ -123,14 +130,6 @@ Indicates the kind of algorithm used for partitioning. ] ``` -### Parameter: `paths` - -List of paths using which data within the container can be partitioned. - -- Required: No -- Type: array -- Default: `[]` - ### Parameter: `tags` Tags of the SQL Database resource. @@ -140,7 +139,7 @@ Tags of the SQL Database resource. ### Parameter: `throughput` -Request Units per second. Will be set to null if autoscaleSettingsMaxThroughput is used. +Default to 400. Request Units per second. Will be ignored if autoscaleSettingsMaxThroughput is used. - Required: No - Type: int diff --git a/avm/res/document-db/database-account/sql-database/container/main.bicep b/avm/res/document-db/database-account/sql-database/container/main.bicep index b1773d699e..2eba5910fa 100644 --- a/avm/res/document-db/database-account/sql-database/container/main.bicep +++ b/avm/res/document-db/database-account/sql-database/container/main.bicep @@ -11,7 +11,7 @@ param sqlDatabaseName string @description('Required. Name of the container.') param name string -@description('Optional. Indicates how long data should be retained in the analytical store, for a container. Analytical store is enabled when ATTL is set with a value other than 0. If the value is set to -1, the analytical store retains all historical data, irrespective of the retention of the data in the transactional store.') +@description('Optional. Default to 0. Indicates how long data should be retained in the analytical store, for a container. Analytical store is enabled when ATTL is set with a value other than 0. If the value is set to -1, the analytical store retains all historical data, irrespective of the retention of the data in the transactional store.') param analyticalStorageTtl int = 0 @description('Optional. The conflict resolution policy for the container. Conflicts and conflict resolution policies are applicable if the Azure Cosmos DB account is configured with multiple write regions.') @@ -19,21 +19,23 @@ param conflictResolutionPolicy object = {} @maxValue(2147483647) @minValue(-1) -@description('Optional. Default time to live (in seconds). With Time to Live or TTL, Azure Cosmos DB provides the ability to delete items automatically from a container after a certain time period. If the value is set to "-1", it is equal to infinity, and items don\'t expire by default.') +@description('Optional. Default to -1. Default time to live (in seconds). With Time to Live or TTL, Azure Cosmos DB provides the ability to delete items automatically from a container after a certain time period. If the value is set to "-1", it is equal to infinity, and items don\'t expire by default.') param defaultTtl int = -1 -@description('Optional. Request Units per second. Will be set to null if autoscaleSettingsMaxThroughput is used.') +@description('Optional. Default to 400. Request Units per second. Will be ignored if autoscaleSettingsMaxThroughput is used.') param throughput int = 400 @maxValue(1000000) -@description('Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to -1, then the property will be set to null and autoscale will be disabled.') +@description('Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to null, then autoscale will be disabled.') param autoscaleSettingsMaxThroughput int? @description('Optional. Tags of the SQL Database resource.') param tags object? -@description('Optional. List of paths using which data within the container can be partitioned.') -param paths array = [] +@maxLength(3) +@minLength(1) +@description('Required. List of paths using which data within the container can be partitioned. For kind=MultiHash it can be up to 3. For anything else it needs to be exactly 1.') +param paths string[] @description('Optional. Indexing policy of the container.') param indexingPolicy object = {} @@ -41,7 +43,7 @@ param indexingPolicy object = {} @description('Optional. The unique key policy configuration containing a list of unique keys that enforces uniqueness constraint on documents in the collection in the Azure Cosmos DB service.') param uniqueKeyPolicyKeys array = [] -@description('Optional. Indicates the kind of algorithm used for partitioning.') +@description('Optional. Default to Hash. Indicates the kind of algorithm used for partitioning.') @allowed([ 'Hash' 'MultiHash' @@ -69,15 +71,16 @@ resource container 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/container id: name indexingPolicy: !empty(indexingPolicy) ? indexingPolicy : null partitionKey: { - paths: paths + paths: [for path in paths: startsWith(path, '/') ? path : '/${path}'] kind: kind + version: kind == 'MultiHash' ? 2 : 1 } uniqueKeyPolicy: !empty(uniqueKeyPolicyKeys) ? { uniqueKeys: uniqueKeyPolicyKeys } : null } options: contains(databaseAccount.properties.capabilities, { name: 'EnableServerless' }) ? null : { - throughput: autoscaleSettingsMaxThroughput == null ? throughput : null + throughput: autoscaleSettingsMaxThroughput == null && throughput != -1 ? throughput : null autoscaleSettings: autoscaleSettingsMaxThroughput != null ? { maxThroughput: autoscaleSettingsMaxThroughput } : null 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 18ea3e8513..f362c2607e 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 @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "15407611441750959399" + "templateHash": "8159752253553558916" }, "name": "DocumentDB Database Account SQL Database Containers", "description": "This module deploys a SQL Database Container in a CosmosDB Account.", @@ -35,7 +35,7 @@ "type": "int", "defaultValue": 0, "metadata": { - "description": "Optional. Indicates how long data should be retained in the analytical store, for a container. Analytical store is enabled when ATTL is set with a value other than 0. If the value is set to -1, the analytical store retains all historical data, irrespective of the retention of the data in the transactional store." + "description": "Optional. Default to 0. Indicates how long data should be retained in the analytical store, for a container. Analytical store is enabled when ATTL is set with a value other than 0. If the value is set to -1, the analytical store retains all historical data, irrespective of the retention of the data in the transactional store." } }, "conflictResolutionPolicy": { @@ -51,14 +51,14 @@ "minValue": -1, "maxValue": 2147483647, "metadata": { - "description": "Optional. Default time to live (in seconds). With Time to Live or TTL, Azure Cosmos DB provides the ability to delete items automatically from a container after a certain time period. If the value is set to \"-1\", it is equal to infinity, and items don't expire by default." + "description": "Optional. Default to -1. Default time to live (in seconds). With Time to Live or TTL, Azure Cosmos DB provides the ability to delete items automatically from a container after a certain time period. If the value is set to \"-1\", it is equal to infinity, and items don't expire by default." } }, "throughput": { "type": "int", "defaultValue": 400, "metadata": { - "description": "Optional. Request Units per second. Will be set to null if autoscaleSettingsMaxThroughput is used." + "description": "Optional. Default to 400. Request Units per second. Will be ignored if autoscaleSettingsMaxThroughput is used." } }, "autoscaleSettingsMaxThroughput": { @@ -66,7 +66,7 @@ "nullable": true, "maxValue": 1000000, "metadata": { - "description": "Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to -1, then the property will be set to null and autoscale will be disabled." + "description": "Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to null, then autoscale will be disabled." } }, "tags": { @@ -78,9 +78,13 @@ }, "paths": { "type": "array", - "defaultValue": [], + "items": { + "type": "string" + }, + "minLength": 1, + "maxLength": 3, "metadata": { - "description": "Optional. List of paths using which data within the container can be partitioned." + "description": "Required. List of paths using which data within the container can be partitioned. For kind=MultiHash it can be up to 3. For anything else it needs to be exactly 1." } }, "indexingPolicy": { @@ -106,7 +110,7 @@ "Range" ], "metadata": { - "description": "Optional. Indicates the kind of algorithm used for partitioning." + "description": "Optional. Default to Hash. Indicates the kind of algorithm used for partitioning." } } }, @@ -139,12 +143,19 @@ "id": "[parameters('name')]", "indexingPolicy": "[if(not(empty(parameters('indexingPolicy'))), parameters('indexingPolicy'), null())]", "partitionKey": { - "paths": "[parameters('paths')]", - "kind": "[parameters('kind')]" + "copy": [ + { + "name": "paths", + "count": "[length(parameters('paths'))]", + "input": "[if(startsWith(parameters('paths')[copyIndex('paths')], '/'), parameters('paths')[copyIndex('paths')], format('/{0}', parameters('paths')[copyIndex('paths')]))]" + } + ], + "kind": "[parameters('kind')]", + "version": "[if(equals(parameters('kind'), 'MultiHash'), 2, 1)]" }, "uniqueKeyPolicy": "[if(not(empty(parameters('uniqueKeyPolicyKeys'))), createObject('uniqueKeys', parameters('uniqueKeyPolicyKeys')), null())]" }, - "options": "[if(contains(reference('databaseAccount').capabilities, createObject('name', 'EnableServerless')), null(), createObject('throughput', if(equals(parameters('autoscaleSettingsMaxThroughput'), null()), parameters('throughput'), null()), 'autoscaleSettings', if(not(equals(parameters('autoscaleSettingsMaxThroughput'), null())), createObject('maxThroughput', parameters('autoscaleSettingsMaxThroughput')), null())))]" + "options": "[if(contains(reference('databaseAccount').capabilities, createObject('name', 'EnableServerless')), null(), createObject('throughput', if(and(equals(parameters('autoscaleSettingsMaxThroughput'), null()), not(equals(parameters('throughput'), -1))), parameters('throughput'), null()), 'autoscaleSettings', if(not(equals(parameters('autoscaleSettingsMaxThroughput'), null())), createObject('maxThroughput', parameters('autoscaleSettingsMaxThroughput')), null())))]" }, "dependsOn": [ "databaseAccount::sqlDatabase" diff --git a/avm/res/document-db/database-account/sql-database/main.bicep b/avm/res/document-db/database-account/sql-database/main.bicep index 98f25d1ff3..8c2a48eaaf 100644 --- a/avm/res/document-db/database-account/sql-database/main.bicep +++ b/avm/res/document-db/database-account/sql-database/main.bicep @@ -9,12 +9,12 @@ param databaseAccountName string param name string @description('Optional. Array of containers to deploy in the SQL database.') -param containers array = [] +param containers object[] = [] -@description('Optional. Request units per second. Will be set to null if autoscaleSettingsMaxThroughput is used.') -param throughput int = 400 +@description('Optional. Request units per second. Will be ignored if autoscaleSettingsMaxThroughput is used.') +param throughput int? -@description('Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to -1, then the property will be set to null and autoscale will be disabled.') +@description('Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to null, then autoscale will be disabled.') param autoscaleSettingsMaxThroughput int? @description('Optional. Tags of the SQL database resource.') @@ -47,15 +47,15 @@ module container 'container/main.bicep' = [for container in containers: { databaseAccountName: databaseAccountName sqlDatabaseName: name name: container.name - analyticalStorageTtl: contains(container, 'analyticalStorageTtl') ? container.analyticalStorageTtl : 0 + analyticalStorageTtl: container.?analyticalStorageTtl autoscaleSettingsMaxThroughput: container.?autoscaleSettingsMaxThroughput - conflictResolutionPolicy: contains(container, 'conflictResolutionPolicy') ? container.conflictResolutionPolicy : {} + conflictResolutionPolicy: container.?conflictResolutionPolicy defaultTtl: container.?defaultTtl - indexingPolicy: contains(container, 'indexingPolicy') ? container.indexingPolicy : {} - kind: contains(container, 'kind') ? container.kind : 'Hash' - paths: contains(container, 'paths') ? container.paths : [] - throughput: contains(container, 'throughput') ? container.throughput : 400 - uniqueKeyPolicyKeys: contains(container, 'uniqueKeyPolicyKeys') ? container.uniqueKeyPolicyKeys : [] + indexingPolicy: container.?indexingPolicy + kind: container.?kind + paths: container.?paths + throughput: (throughput != null || autoscaleSettingsMaxThroughput != null) && container.?throughput == null ? -1 : container.?throughput + uniqueKeyPolicyKeys: container.?uniqueKeyPolicyKeys } }] 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 e57bc190b0..ca95db8b40 100644 --- a/avm/res/document-db/database-account/sql-database/main.json +++ b/avm/res/document-db/database-account/sql-database/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "3371007626132936503" + "templateHash": "1307928694299767068" }, "name": "DocumentDB Database Account SQL Databases", "description": "This module deploys a SQL Database in a CosmosDB Account.", @@ -27,6 +27,9 @@ }, "containers": { "type": "array", + "items": { + "type": "object" + }, "defaultValue": [], "metadata": { "description": "Optional. Array of containers to deploy in the SQL database." @@ -34,16 +37,16 @@ }, "throughput": { "type": "int", - "defaultValue": 400, + "nullable": true, "metadata": { - "description": "Optional. Request units per second. Will be set to null if autoscaleSettingsMaxThroughput is used." + "description": "Optional. Request units per second. Will be ignored if autoscaleSettingsMaxThroughput is used." } }, "autoscaleSettingsMaxThroughput": { "type": "int", "nullable": true, "metadata": { - "description": "Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to -1, then the property will be set to null and autoscale will be disabled." + "description": "Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to null, then autoscale will be disabled." } }, "tags": { @@ -99,19 +102,31 @@ "name": { "value": "[parameters('containers')[copyIndex()].name]" }, - "analyticalStorageTtl": "[if(contains(parameters('containers')[copyIndex()], 'analyticalStorageTtl'), createObject('value', parameters('containers')[copyIndex()].analyticalStorageTtl), createObject('value', 0))]", + "analyticalStorageTtl": { + "value": "[tryGet(parameters('containers')[copyIndex()], 'analyticalStorageTtl')]" + }, "autoscaleSettingsMaxThroughput": { "value": "[tryGet(parameters('containers')[copyIndex()], 'autoscaleSettingsMaxThroughput')]" }, - "conflictResolutionPolicy": "[if(contains(parameters('containers')[copyIndex()], 'conflictResolutionPolicy'), createObject('value', parameters('containers')[copyIndex()].conflictResolutionPolicy), createObject('value', createObject()))]", + "conflictResolutionPolicy": { + "value": "[tryGet(parameters('containers')[copyIndex()], 'conflictResolutionPolicy')]" + }, "defaultTtl": { "value": "[tryGet(parameters('containers')[copyIndex()], 'defaultTtl')]" }, - "indexingPolicy": "[if(contains(parameters('containers')[copyIndex()], 'indexingPolicy'), createObject('value', parameters('containers')[copyIndex()].indexingPolicy), createObject('value', createObject()))]", - "kind": "[if(contains(parameters('containers')[copyIndex()], 'kind'), createObject('value', parameters('containers')[copyIndex()].kind), createObject('value', 'Hash'))]", - "paths": "[if(contains(parameters('containers')[copyIndex()], 'paths'), createObject('value', parameters('containers')[copyIndex()].paths), createObject('value', createArray()))]", - "throughput": "[if(contains(parameters('containers')[copyIndex()], 'throughput'), createObject('value', parameters('containers')[copyIndex()].throughput), createObject('value', 400))]", - "uniqueKeyPolicyKeys": "[if(contains(parameters('containers')[copyIndex()], 'uniqueKeyPolicyKeys'), createObject('value', parameters('containers')[copyIndex()].uniqueKeyPolicyKeys), createObject('value', createArray()))]" + "indexingPolicy": { + "value": "[tryGet(parameters('containers')[copyIndex()], 'indexingPolicy')]" + }, + "kind": { + "value": "[tryGet(parameters('containers')[copyIndex()], 'kind')]" + }, + "paths": { + "value": "[tryGet(parameters('containers')[copyIndex()], 'paths')]" + }, + "throughput": "[if(and(or(not(equals(parameters('throughput'), null())), not(equals(parameters('autoscaleSettingsMaxThroughput'), null()))), equals(tryGet(parameters('containers')[copyIndex()], 'throughput'), null())), createObject('value', -1), createObject('value', tryGet(parameters('containers')[copyIndex()], 'throughput')))]", + "uniqueKeyPolicyKeys": { + "value": "[tryGet(parameters('containers')[copyIndex()], 'uniqueKeyPolicyKeys')]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -121,7 +136,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "15407611441750959399" + "templateHash": "8159752253553558916" }, "name": "DocumentDB Database Account SQL Database Containers", "description": "This module deploys a SQL Database Container in a CosmosDB Account.", @@ -150,7 +165,7 @@ "type": "int", "defaultValue": 0, "metadata": { - "description": "Optional. Indicates how long data should be retained in the analytical store, for a container. Analytical store is enabled when ATTL is set with a value other than 0. If the value is set to -1, the analytical store retains all historical data, irrespective of the retention of the data in the transactional store." + "description": "Optional. Default to 0. Indicates how long data should be retained in the analytical store, for a container. Analytical store is enabled when ATTL is set with a value other than 0. If the value is set to -1, the analytical store retains all historical data, irrespective of the retention of the data in the transactional store." } }, "conflictResolutionPolicy": { @@ -166,14 +181,14 @@ "minValue": -1, "maxValue": 2147483647, "metadata": { - "description": "Optional. Default time to live (in seconds). With Time to Live or TTL, Azure Cosmos DB provides the ability to delete items automatically from a container after a certain time period. If the value is set to \"-1\", it is equal to infinity, and items don't expire by default." + "description": "Optional. Default to -1. Default time to live (in seconds). With Time to Live or TTL, Azure Cosmos DB provides the ability to delete items automatically from a container after a certain time period. If the value is set to \"-1\", it is equal to infinity, and items don't expire by default." } }, "throughput": { "type": "int", "defaultValue": 400, "metadata": { - "description": "Optional. Request Units per second. Will be set to null if autoscaleSettingsMaxThroughput is used." + "description": "Optional. Default to 400. Request Units per second. Will be ignored if autoscaleSettingsMaxThroughput is used." } }, "autoscaleSettingsMaxThroughput": { @@ -181,7 +196,7 @@ "nullable": true, "maxValue": 1000000, "metadata": { - "description": "Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to -1, then the property will be set to null and autoscale will be disabled." + "description": "Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to null, then autoscale will be disabled." } }, "tags": { @@ -193,9 +208,13 @@ }, "paths": { "type": "array", - "defaultValue": [], + "items": { + "type": "string" + }, + "minLength": 1, + "maxLength": 3, "metadata": { - "description": "Optional. List of paths using which data within the container can be partitioned." + "description": "Required. List of paths using which data within the container can be partitioned. For kind=MultiHash it can be up to 3. For anything else it needs to be exactly 1." } }, "indexingPolicy": { @@ -221,7 +240,7 @@ "Range" ], "metadata": { - "description": "Optional. Indicates the kind of algorithm used for partitioning." + "description": "Optional. Default to Hash. Indicates the kind of algorithm used for partitioning." } } }, @@ -254,12 +273,19 @@ "id": "[parameters('name')]", "indexingPolicy": "[if(not(empty(parameters('indexingPolicy'))), parameters('indexingPolicy'), null())]", "partitionKey": { - "paths": "[parameters('paths')]", - "kind": "[parameters('kind')]" + "copy": [ + { + "name": "paths", + "count": "[length(parameters('paths'))]", + "input": "[if(startsWith(parameters('paths')[copyIndex('paths')], '/'), parameters('paths')[copyIndex('paths')], format('/{0}', parameters('paths')[copyIndex('paths')]))]" + } + ], + "kind": "[parameters('kind')]", + "version": "[if(equals(parameters('kind'), 'MultiHash'), 2, 1)]" }, "uniqueKeyPolicy": "[if(not(empty(parameters('uniqueKeyPolicyKeys'))), createObject('uniqueKeys', parameters('uniqueKeyPolicyKeys')), null())]" }, - "options": "[if(contains(reference('databaseAccount').capabilities, createObject('name', 'EnableServerless')), null(), createObject('throughput', if(equals(parameters('autoscaleSettingsMaxThroughput'), null()), parameters('throughput'), null()), 'autoscaleSettings', if(not(equals(parameters('autoscaleSettingsMaxThroughput'), null())), createObject('maxThroughput', parameters('autoscaleSettingsMaxThroughput')), null())))]" + "options": "[if(contains(reference('databaseAccount').capabilities, createObject('name', 'EnableServerless')), null(), createObject('throughput', if(and(equals(parameters('autoscaleSettingsMaxThroughput'), null()), not(equals(parameters('throughput'), -1))), parameters('throughput'), null()), 'autoscaleSettings', if(not(equals(parameters('autoscaleSettingsMaxThroughput'), null())), createObject('maxThroughput', parameters('autoscaleSettingsMaxThroughput')), null())))]" }, "dependsOn": [ "databaseAccount::sqlDatabase" 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 new file mode 100644 index 0000000000..7be10fac8a --- /dev/null +++ b/avm/res/document-db/database-account/tests/e2e/analytical/main.test.bicep @@ -0,0 +1,58 @@ +targetScope = 'subscription' + +metadata name = 'Using analytical storage' +metadata description = 'This instance deploys the module with analytical storage enabled.' + +// ========== // +// 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. 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 = '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 +var enforcedLocation = 'eastus' + +// ============== // +// General resources +// ============== // +resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { + name: resourceGroupName + location: enforcedLocation +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../../main.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}' + params: { + location: enforcedLocation + enableAnalyticalStorage: true + name: '${namePrefix}-analytical' + locations: [ + { + failoverPriority: 0 + isZoneRedundant: false + locationName: enforcedLocation + } + ] + sqlDatabases: [ + { + name: 'empty-database' + } + ] + } +} diff --git a/avm/res/document-db/database-account/tests/e2e/autoFailoverOff/dependencies.bicep b/avm/res/document-db/database-account/tests/e2e/autoFailoverOff/dependencies.bicep new file mode 100644 index 0000000000..9d1494c200 --- /dev/null +++ b/avm/res/document-db/database-account/tests/e2e/autoFailoverOff/dependencies.bicep @@ -0,0 +1,46 @@ +@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/autoFailoverOff/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/autoFailoverOff/main.test.bicep new file mode 100644 index 0000000000..7e83765872 --- /dev/null +++ b/avm/res/document-db/database-account/tests/e2e/autoFailoverOff/main.test.bicep @@ -0,0 +1,77 @@ +targetScope = 'subscription' + +metadata name = 'Without automatic failover' +metadata description = 'This instance deploys the module disabling automatic failover.' + +// ========== // +// 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. 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 = 'dddaauo' + +@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 +var enforcedLocation = 'eastus' + +// ============ // +// 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}' + } +} + +// ============== // +// General resources +// ============== // +resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { + name: resourceGroupName + location: enforcedLocation +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../../main.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}' + params: { + automaticFailover: false + location: enforcedLocation + name: '${namePrefix}-auto-failover-off' + locations: [ + { + failoverPriority: 0 + isZoneRedundant: false + locationName: enforcedLocation + } + { + failoverPriority: 1 + isZoneRedundant: false + locationName: nestedDependencies.outputs.pairedRegionName + } + ] + sqlDatabases: [ + { + name: 'empty-database' + } + ] + } +} diff --git a/avm/res/document-db/database-account/tests/e2e/consistency/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/consistency/main.test.bicep new file mode 100644 index 0000000000..8dbaa8440e --- /dev/null +++ b/avm/res/document-db/database-account/tests/e2e/consistency/main.test.bicep @@ -0,0 +1,60 @@ +targetScope = 'subscription' + +metadata name = 'Using bounded consistency' +metadata description = 'This instance deploys the module specifying a default consistency level.' + +// ========== // +// 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. 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 = '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 +var enforcedLocation = 'eastus' + +// ============== // +// General resources +// ============== // +resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { + name: resourceGroupName + location: enforcedLocation +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../../main.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}' + params: { + location: enforcedLocation + name: '${namePrefix}-bounded' + defaultConsistencyLevel: 'BoundedStaleness' + maxIntervalInSeconds: 600 + maxStalenessPrefix: 200000 + locations: [ + { + failoverPriority: 0 + isZoneRedundant: false + locationName: enforcedLocation + } + ] + sqlDatabases: [ + { + name: 'empty-database' + } + ] + } +} diff --git a/avm/res/document-db/database-account/tests/e2e/continousBckup/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/continousBckup/main.test.bicep new file mode 100644 index 0000000000..0f4d2dda33 --- /dev/null +++ b/avm/res/document-db/database-account/tests/e2e/continousBckup/main.test.bicep @@ -0,0 +1,59 @@ +targetScope = 'subscription' + +metadata name = 'Enabling continous backups' +metadata description = 'This instance deploys the module enabling continous backups.' + +// ========== // +// 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. 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 = 'dddacbc' + +@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 +var enforcedLocation = 'eastus' + +// ============== // +// General resources +// ============== // +resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { + name: resourceGroupName + location: enforcedLocation +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../../main.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}' + params: { + location: enforcedLocation + name: '${namePrefix}-continous-bckup' + backupPolicyType: 'Continuous' + backupPolicyContinuousTier: 'Continuous7Days' + locations: [ + { + failoverPriority: 0 + isZoneRedundant: false + locationName: enforcedLocation + } + ] + sqlDatabases: [ + { + name: 'empty-database' + } + ] + } +} 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 af0711d8c6..d925e18d86 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 @@ -20,6 +20,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 +var enforcedLocation = 'eastus' + // ============ // // Dependencies // // ============ // @@ -28,7 +31,7 @@ param namePrefix string = '#_namePrefix_#' // ================= resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { name: resourceGroupName - location: resourceLocation + location: enforcedLocation } // ============== // @@ -38,15 +41,15 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { @batchSize(1) 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 locations: [ { failoverPriority: 0 isZoneRedundant: false - locationName: resourceLocation + locationName: enforcedLocation } ] } diff --git a/avm/res/document-db/database-account/tests/e2e/disableLocal/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/disableLocal/main.test.bicep new file mode 100644 index 0000000000..78320d234b --- /dev/null +++ b/avm/res/document-db/database-account/tests/e2e/disableLocal/main.test.bicep @@ -0,0 +1,57 @@ +targetScope = 'subscription' + +metadata name = 'Disabling local authentication. i.e. access keys' +metadata description = 'This instance deploys the module disabling local authentication.' + +// ========== // +// 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. 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 = 'dddadlo' + +@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 +var enforcedLocation = 'eastus' + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { + name: resourceGroupName + location: enforcedLocation +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../../main.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}' + params: { + disableLocalAuth: true + location: enforcedLocation + name: '${namePrefix}-local-auth-off' + locations: [ + { + failoverPriority: 0 + isZoneRedundant: false + locationName: enforcedLocation + } + ] + sqlDatabases: [ + { + name: 'empty-database' + } + ] + } +} 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 9931f2cbd2..9e03bcf942 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 @@ -1,6 +1,6 @@ targetScope = 'subscription' -metadata name = 'Germlin Database' +metadata name = 'Gremlin Database' metadata description = 'This instance deploys the module with a Gremlin Database.' // ========== // @@ -20,6 +20,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 +var enforcedLocation = 'eastus' + // ============ // // Dependencies // // ============ // @@ -28,16 +31,16 @@ param namePrefix string = '#_namePrefix_#' // ================= resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-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: { managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' pairedRegionScriptName: 'dep-${namePrefix}-ds-${serviceShort}' - location: resourceLocation + location: enforcedLocation } } @@ -45,13 +48,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 } } @@ -62,14 +65,14 @@ 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}' + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}-${iteration}' params: { name: '${namePrefix}${serviceShort}002' locations: [ { failoverPriority: 0 isZoneRedundant: false - locationName: resourceLocation + locationName: enforcedLocation } { failoverPriority: 1 @@ -143,7 +146,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' name: '${namePrefix}-gdb-${serviceShort}-002' } ] - location: resourceLocation + location: enforcedLocation roleAssignments: [ { roleDefinitionIdOrName: 'Owner' 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 463ff7708e..e3fd85af54 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 @@ -20,6 +20,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 +var enforcedLocation = 'eastus' + // ============ // // Dependencies // // ============ // @@ -28,16 +31,16 @@ param namePrefix string = '#_namePrefix_#' // ================= resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-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: { managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' pairedRegionScriptName: 'dep-${namePrefix}-ds-${serviceShort}' - location: resourceLocation + location: enforcedLocation } } @@ -45,13 +48,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 } } @@ -62,14 +65,14 @@ 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}' + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}-${iteration}' params: { name: '${namePrefix}${serviceShort}001' locations: [ { failoverPriority: 0 isZoneRedundant: false - locationName: resourceLocation + locationName: enforcedLocation } { failoverPriority: 1 @@ -91,7 +94,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } ] - location: resourceLocation + location: enforcedLocation mongodbDatabases: [ { collections: [ diff --git a/avm/res/document-db/database-account/tests/e2e/periodicBckup/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/periodicBckup/main.test.bicep new file mode 100644 index 0000000000..d7eb9f3683 --- /dev/null +++ b/avm/res/document-db/database-account/tests/e2e/periodicBckup/main.test.bicep @@ -0,0 +1,61 @@ +targetScope = 'subscription' + +metadata name = 'Using periodic backups' +metadata description = 'This instance deploys the module enabling periodic backups.' + +// ========== // +// 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. 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 = 'dddapbc' + +@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 +var enforcedLocation = 'eastus' + +// ============== // +// General resources +// ============== // +resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { + name: resourceGroupName + location: enforcedLocation +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../../main.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}' + params: { + location: enforcedLocation + name: '${namePrefix}-periodic-bckup' + backupPolicyType: 'Periodic' + backupIntervalInMinutes: 300 + backupStorageRedundancy: 'Zone' + backupRetentionIntervalInHours: 16 + locations: [ + { + failoverPriority: 0 + isZoneRedundant: false + locationName: enforcedLocation + } + ] + sqlDatabases: [ + { + name: 'empty-database' + } + ] + } +} diff --git a/avm/res/document-db/database-account/tests/e2e/plain/dependencies.bicep b/avm/res/document-db/database-account/tests/e2e/plain/dependencies.bicep index e24e1d1778..067f558eb5 100644 --- a/avm/res/document-db/database-account/tests/e2e/plain/dependencies.bicep +++ b/avm/res/document-db/database-account/tests/e2e/plain/dependencies.bicep @@ -4,46 +4,13 @@ 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 +@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/document-db/database-account/tests/e2e/plain/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/plain/main.test.bicep index c67998598b..0c9adcc64d 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 @@ -20,38 +20,42 @@ 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 +var enforcedLocation = 'eastus' + // ============ // // 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' + name: '${uniqueString(deployment().name, enforcedLocation)}-nestedDependencies' params: { managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' - pairedRegionScriptName: 'dep-${namePrefix}-ds-${serviceShort}' - location: resourceLocation + location: enforcedLocation } } +// ============== // +// General resources +// ============== // +resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { + name: resourceGroupName + location: enforcedLocation +} + +// ============== // // Diagnostics -// =========== +// ============== // 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 } } @@ -62,20 +66,15 @@ 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}' + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}-${iteration}' params: { name: '${namePrefix}${serviceShort}001' - location: resourceLocation + location: enforcedLocation locations: [ { failoverPriority: 0 isZoneRedundant: false - locationName: resourceLocation - } - { - failoverPriority: 1 - isZoneRedundant: false - locationName: nestedDependencies.outputs.pairedRegionName + locationName: enforcedLocation } ] diagnosticSettings: [ diff --git a/avm/res/document-db/database-account/tests/e2e/sqldb/dependencies.bicep b/avm/res/document-db/database-account/tests/e2e/sqldb/dependencies.bicep deleted file mode 100644 index cd88a1370a..0000000000 --- a/avm/res/document-db/database-account/tests/e2e/sqldb/dependencies.bicep +++ /dev/null @@ -1,117 +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 Virtual Network to create.') -param virtualNetworkName string - -@description('Required. The name of the Deployment Script to create to get the paired region name.') -param pairedRegionScriptName string - -var addressPrefix = '10.0.0.0/16' - -resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: managedIdentityName - location: location -} - -resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { - name: virtualNetworkName - location: location - properties: { - addressSpace: { - addressPrefixes: [ - addressPrefix - ] - } - subnets: [ - { - name: 'defaultSubnet' - properties: { - addressPrefix: cidrSubnet(addressPrefix, 20, 0) - } - } - { - name: 'custom-private-subnet' - properties: { - addressPrefix: cidrSubnet(addressPrefix, 20, 1) - } - } - { - name: 'custom-private-subnet-2' - properties: { - addressPrefix: cidrSubnet(addressPrefix, 20, 2) - } - } - ] - } -} - -resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { - name: 'privatelink.documents.azure.com' - location: 'global' - - resource virtualNetworkLinks 'virtualNetworkLinks@2020-06-01' = { - name: '${virtualNetwork.name}-vnetlink' - location: 'global' - properties: { - virtualNetwork: { - id: virtualNetwork.id - } - registrationEnabled: false - } - } -} - -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 - -@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 - -@description('The resource ID of the created Virtual Network Default Subnet.') -output defaultSubnetResourceId string = virtualNetwork.properties.subnets[0].id - -@description('The resource ID of the 2nd created Virtual Network Subnet.') -output customSubnet1ResourceId string = virtualNetwork.properties.subnets[1].id - -@description('The resource ID of the 3rd created Virtual Network Subnet.') -output customSubnet2ResourceId string = virtualNetwork.properties.subnets[2].id - -@description('The resource ID of the created Private DNS Zone.') -output privateDNSZoneResourceId string = privateDNSZone.id 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 4a839dd38f..113f8a0e2e 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 @@ -20,40 +20,15 @@ param serviceShort string = 'dddasql' @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' -// ============ // -// Dependencies // -// ============ // +// Pipeline is selecting random regions which dont support all cosmos features and have constraints when creating new cosmos +var enforcedLocation = 'eastus' +// ============== // // 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: { - managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' - virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' - pairedRegionScriptName: 'dep-${namePrefix}-ds-${serviceShort}' - location: resourceLocation - } -} - -// Diagnostics -// =========== -module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-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 } // ============== // @@ -62,72 +37,16 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t module testDeployment '../../../main.bicep' = { scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}' + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}' params: { + location: enforcedLocation + enableAnalyticalStorage: true name: '${namePrefix}${serviceShort}001' locations: [ { failoverPriority: 0 isZoneRedundant: false - locationName: resourceLocation - } - { - failoverPriority: 1 - isZoneRedundant: false - locationName: nestedDependencies.outputs.pairedRegionName - } - ] - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - location: resourceLocation - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - service: 'Sql' - subnetResourceId: nestedDependencies.outputs.customSubnet1ResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - service: 'Sql' - subnetResourceId: nestedDependencies.outputs.customSubnet2ResourceId - } - ] - 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' + locationName: enforcedLocation } ] sqlDatabases: [ @@ -163,29 +82,80 @@ module testDeployment '../../../main.bicep' = { throughput: 600 } ] - name: '${namePrefix}-sql-${serviceShort}-001' - } - { - containers: [] - name: '${namePrefix}-sql-${serviceShort}-002' + name: 'all-configs-specified' } { containers: [ { - kind: 'Hash' - name: 'container-003' - autoscaleSettingsMaxThroughput: 1000 + name: 'container-001' indexingPolicy: { automatic: true } paths: [ '/myPartitionKey' ] - analyticalStorageTtl: 0 + } + ] + name: 'automatic-indexing-policy' + } + { + containers: [ + { + name: 'container-001' + paths: [ + '/myPartitionKey' + ] conflictResolutionPolicy: { conflictResolutionPath: '/myCustomId' mode: 'LastWriterWins' } + } + ] + name: 'last-writer-conflict-resolution-policy' + } + { + containers: [ + { + name: 'container-001' + paths: [ + '/myPartitionKey' + ] + analyticalStorageTtl: 1000 + } + ] + name: 'fixed-analytical-ttl' + } + { + containers: [ + { + name: 'container-001' + paths: [ + '/myPartitionKey' + ] + analyticalStorageTtl: -1 + } + ] + name: 'infinite-analytical-ttl' + } + { + containers: [ + { + name: 'container-001' + paths: [ + '/myPartitionKey' + ] + defaultTtl: 1000 + } + ] + name: 'document-ttl' + } + { + containers: [ + { + name: 'container-001' + paths: [ + '/myPartitionKey' + ] uniqueKeyPolicyKeys: [ { paths: [ @@ -200,23 +170,126 @@ module testDeployment '../../../main.bicep' = { ] } ] - name: '${namePrefix}-sql-${serviceShort}-003' + name: 'unique-key-policy' + } + { + containers: [ + { + name: 'container-003' + throughput: 500 + paths: [ + '/myPartitionKey' + ] + } + ] + name: 'db-and-container-fixed-throughput-level' + throughput: 500 + } + { + containers: [ + { + name: 'container-003' + throughput: 500 + paths: [ + '/myPartitionKey' + ] + } + ] + name: 'container-fixed-throughput-level' + } + { + containers: [ + { + name: 'container-003' + paths: [ + '/myPartitionKey' + ] + } + ] + name: 'database-fixed-throughput-level' + throughput: 500 + } + { + containers: [ + { + name: 'container-003' + autoscaleSettingsMaxThroughput: 1000 + paths: [ + '/myPartitionKey' + ] + } + ] + name: 'db-and-container-autoscale-level' autoscaleSettingsMaxThroughput: 1000 } + { + containers: [ + { + name: 'container-003' + autoscaleSettingsMaxThroughput: 1000 + paths: [ + '/myPartitionKey' + ] + } + ] + name: 'container-autoscale-level' + } + { + containers: [ + { + name: 'container-003' + paths: [ + '/myPartitionKey' + ] + } + ] + name: 'database-autoscale-level' + autoscaleSettingsMaxThroughput: 1000 + } + { + containers: [ + { + name: 'container-001' + kind: 'MultiHash' + paths: [ + '/myPartitionKey1' + '/myPartitionKey2' + '/myPartitionKey3' + ] + } + { + name: 'container-002' + kind: 'MultiHash' + paths: [ + 'myPartitionKey1' + 'myPartitionKey2' + 'myPartitionKey3' + ] + } + { + name: 'container-003' + kind: 'Hash' + paths: [ + '/myPartitionKey1' + ] + } + { + name: 'container-004' + kind: 'Hash' + paths: [ + 'myPartitionKey1' + ] + } + ] + name: 'all-partition-key-types' + } + { + containers: [] + name: 'empty-containers-array' + } + { + name: 'no-containers-specified' + } ] - managedIdentities: { - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] } diff --git a/avm/res/document-db/database-account/tests/e2e/systemMi/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/systemMi/main.test.bicep new file mode 100644 index 0000000000..bc2c279055 --- /dev/null +++ b/avm/res/document-db/database-account/tests/e2e/systemMi/main.test.bicep @@ -0,0 +1,55 @@ +targetScope = 'subscription' + +metadata name = 'Deploying with a System-Assigned Identity' +metadata description = 'This instance deploys the module with an assigned system assigned managed identity.' + +// ========== // +// 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. 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 = 'dddasmi' + +@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 +var enforcedLocation = 'eastus' + +// ============== // +// General resources +// ============== // +resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { + name: resourceGroupName + location: enforcedLocation +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../../main.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}' + params: { + location: enforcedLocation + name: '${namePrefix}-system-mi' + locations: [ + { + failoverPriority: 0 + isZoneRedundant: false + locationName: enforcedLocation + } + ] + managedIdentities: { + systemAssigned: true + } + } +} diff --git a/avm/res/document-db/database-account/tests/e2e/userMi/dependencies.bicep b/avm/res/document-db/database-account/tests/e2e/userMi/dependencies.bicep new file mode 100644 index 0000000000..067f558eb5 --- /dev/null +++ b/avm/res/document-db/database-account/tests/e2e/userMi/dependencies.bicep @@ -0,0 +1,16 @@ +@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 + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { + name: managedIdentityName + location: location +} + +@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/document-db/database-account/tests/e2e/userMi/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/userMi/main.test.bicep new file mode 100644 index 0000000000..4db70eaae4 --- /dev/null +++ b/avm/res/document-db/database-account/tests/e2e/userMi/main.test.bicep @@ -0,0 +1,73 @@ +targetScope = 'subscription' + +metadata name = 'Deploying with a User-Assigned Identity' +metadata description = 'This instance deploys the module with an assigned user assigned managed identity.' + +// ========== // +// 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. 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 = '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 +var enforcedLocation = 'eastus' + +// ============ // +// Dependencies // +// ============ // + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-nestedDependencies' + params: { + location: enforcedLocation + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + } +} + +// ============== // +// General resources +// ============== // +resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { + name: resourceGroupName + location: enforcedLocation +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../../main.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}' + params: { + location: enforcedLocation + name: '${namePrefix}-user-mi' + locations: [ + { + failoverPriority: 0 + isZoneRedundant: false + locationName: enforcedLocation + } + ] + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + } + dependsOn: [ + nestedDependencies + ] +} 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 7829519f3d..add79ea3be 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 @@ -22,39 +22,44 @@ 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 +var enforcedLocation = 'eastus' + // ============ // // 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' + name: '${uniqueString(deployment().name, enforcedLocation)}-nestedDependencies' params: { managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' pairedRegionScriptName: 'dep-${namePrefix}-ds-${serviceShort}' - location: resourceLocation + location: enforcedLocation } } +// ============== // +// General resources +// ============== // +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: enforcedLocation +} + +// ============ // // Diagnostics -// =========== +// ============ // 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,14 +69,14 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t module testDeployment '../../../main.bicep' = { scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}' + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}' params: { name: '${namePrefix}${serviceShort}001' locations: [ { failoverPriority: 0 isZoneRedundant: false - locationName: resourceLocation + locationName: enforcedLocation } { failoverPriority: 1 @@ -87,7 +92,7 @@ module testDeployment '../../../main.bicep' = { workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } ] - location: resourceLocation + location: enforcedLocation privateEndpoints: [ { privateDnsZoneResourceIds: [ diff --git a/avm/res/document-db/database-account/tests/e2e/zoneRedundant/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/zoneRedundant/main.test.bicep new file mode 100644 index 0000000000..a8db0dad34 --- /dev/null +++ b/avm/res/document-db/database-account/tests/e2e/zoneRedundant/main.test.bicep @@ -0,0 +1,52 @@ +targetScope = 'subscription' + +metadata name = 'Using zone redundant regions' +metadata description = 'This instance deploys the module enabling multiple zone redundant in multiple regions.' + +// ========== // +// 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. 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 = 'dddazr' + +@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 +var enforcedLocation = 'eastus' + +// ============== // +// General resources +// ============== // +resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { + name: resourceGroupName + location: enforcedLocation +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../../main.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}' + params: { + location: enforcedLocation + name: '${namePrefix}-zone-redundant' + locations: [ + { + failoverPriority: 0 + isZoneRedundant: true + locationName: enforcedLocation + } + ] + } +} From 47c34b486a832f6acc6c1382036c5dc0dbd5fcc3 Mon Sep 17 00:00:00 2001 From: Rainer Halanek <61878316+rahalan@users.noreply.github.com> Date: Wed, 13 Mar 2024 17:15:58 +0100 Subject: [PATCH 16/73] feat: New Module `avm/res/compute/virtual-machine-scale-set`, migrated from CARML (#1210) Migrate VM scale set from CARML successful run (is shown red, but actually it worked, see link): [![avm.res.compute.virtual-machine-scale-set](https://github.com/rahalan/bicep-registry-modules/actions/workflows/avm.res.compute.virtual-machine-scale-set.yml/badge.svg?branch=users%2Frahalan%2FAddVMSS)](https://github.com/rahalan/bicep-registry-modules/actions/workflows/avm.res.compute.virtual-machine-scale-set.yml) --------- Co-authored-by: Kris Baranek Co-authored-by: Alexander Sehr --- .github/CODEOWNERS | 2 +- .github/ISSUE_TEMPLATE/avm_module_issue.yml | 2 +- ....res.compute.virtual-machine-scale-set.yml | 85 + .../virtual-machine-scale-set/README.md | 2504 +++++++++++++++++ .../extension/README.md | 143 + .../extension/main.bicep | 66 + .../extension/main.json | 127 + .../virtual-machine-scale-set/main.bicep | 740 +++++ .../virtual-machine-scale-set/main.json | 2362 ++++++++++++++++ .../e2e/linux.defaults/dependencies.bicep | 86 + .../tests/e2e/linux.defaults/main.test.bicep | 96 + .../tests/e2e/linux.max/dependencies.bicep | 193 ++ .../tests/e2e/linux.max/main.test.bicep | 211 ++ .../tests/e2e/linux.ssecmk/dependencies.bicep | 148 + .../tests/e2e/linux.ssecmk/main.test.bicep | 120 + .../e2e/windows.defaults/dependencies.bicep | 30 + .../e2e/windows.defaults/main.test.bicep | 91 + .../tests/e2e/windows.max/dependencies.bicep | 155 + .../tests/e2e/windows.max/main.test.bicep | 205 ++ .../windows.waf-aligned/dependencies.bicep | 155 + .../e2e/windows.waf-aligned/main.test.bicep | 194 ++ .../virtual-machine-scale-set/version.json | 7 + 22 files changed, 7720 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/avm.res.compute.virtual-machine-scale-set.yml create mode 100644 avm/res/compute/virtual-machine-scale-set/README.md create mode 100644 avm/res/compute/virtual-machine-scale-set/extension/README.md create mode 100644 avm/res/compute/virtual-machine-scale-set/extension/main.bicep create mode 100644 avm/res/compute/virtual-machine-scale-set/extension/main.json create mode 100644 avm/res/compute/virtual-machine-scale-set/main.bicep create mode 100644 avm/res/compute/virtual-machine-scale-set/main.json create mode 100644 avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.defaults/dependencies.bicep create mode 100644 avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.defaults/main.test.bicep create mode 100644 avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.max/dependencies.bicep create mode 100644 avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.max/main.test.bicep create mode 100644 avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.ssecmk/dependencies.bicep create mode 100644 avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.ssecmk/main.test.bicep create mode 100644 avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.defaults/dependencies.bicep create mode 100644 avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.defaults/main.test.bicep create mode 100644 avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.max/dependencies.bicep create mode 100644 avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.max/main.test.bicep create mode 100644 avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.waf-aligned/dependencies.bicep create mode 100644 avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.waf-aligned/main.test.bicep create mode 100644 avm/res/compute/virtual-machine-scale-set/version.json diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 28f99373e3..19091cd52b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -29,7 +29,7 @@ /avm/res/compute/proximity-placement-group/ @Azure/avm-res-compute-proximityplacementgroup-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/compute/ssh-public-key/ @Azure/avm-res-compute-sshpublickey-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/compute/virtual-machine/ @Azure/avm-res-compute-virtualmachine-module-owners-bicep @Azure/avm-core-team-technical-bicep -#/avm/res/compute/virtual-machine-scale-set/ @Azure/avm-res-compute-virtualmachinescaleset-module-owners-bicep @Azure/avm-core-team-technical-bicep +/avm/res/compute/virtual-machine-scale-set/ @Azure/avm-res-compute-virtualmachinescaleset-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/consumption/budget/ @Azure/avm-res-consumption-budget-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/container-instance/container-group/ @Azure/avm-res-containerinstance-containergroup-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/container-registry/registry/ @Azure/avm-res-containerregistry-registry-module-owners-bicep @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 8719866367..39a45a8751 100644 --- a/.github/ISSUE_TEMPLATE/avm_module_issue.yml +++ b/.github/ISSUE_TEMPLATE/avm_module_issue.yml @@ -63,7 +63,7 @@ body: - "avm/res/compute/proximity-placement-group" - "avm/res/compute/ssh-public-key" - "avm/res/compute/virtual-machine" - # - "avm/res/compute/virtual-machine-scale-set" + - "avm/res/compute/virtual-machine-scale-set" - "avm/res/consumption/budget" # - "avm/res/container-instance/container-group" - "avm/res/container-registry/registry" diff --git a/.github/workflows/avm.res.compute.virtual-machine-scale-set.yml b/.github/workflows/avm.res.compute.virtual-machine-scale-set.yml new file mode 100644 index 0000000000..4fde36170e --- /dev/null +++ b/.github/workflows/avm.res.compute.virtual-machine-scale-set.yml @@ -0,0 +1,85 @@ +name: "avm.res.compute.virtual-machine-scale-set" + +on: + schedule: + - cron: "0 12 1/15 * *" # Bi-Weekly Test (on 1st & 15th of month) + 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 + push: + branches: + - main + paths: + - ".github/actions/templates/avm-**" + - ".github/workflows/avm.template.module.yml" + - ".github/workflows/avm.res.compute.virtual-machine-scale-set.yml" + - "avm/res/compute/virtual-machine-scale-set/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/compute/virtual-machine-scale-set" + workflowPath: ".github/workflows/avm.res.compute.virtual-machine-scale-set.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-latest + name: "Initialize pipeline" + steps: + - name: "Checkout" + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: "Set input parameters to output variables" + id: get-workflow-param + uses: ./.github/actions/templates/avm-getWorkflowInput + with: + workflowPath: "${{ env.workflowPath}}" + - name: "Get module test file paths" + id: get-module-test-file-paths + uses: ./.github/actions/templates/avm-getModuleTestFiles + with: + modulePath: "${{ env.modulePath }}" + outputs: + workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }} + moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} + psRuleModuleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.psRuleModuleTestFilePaths }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Run" + permissions: + id-token: write # For OIDC + contents: write # For release tags + needs: + - job_initialize_pipeline + uses: ./.github/workflows/avm.template.module.yml + with: + workflowInput: "${{ needs.job_initialize_pipeline.outputs.workflowInput }}" + moduleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.moduleTestFilePaths }}" + psRuleModuleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.psRuleModuleTestFilePaths }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit diff --git a/avm/res/compute/virtual-machine-scale-set/README.md b/avm/res/compute/virtual-machine-scale-set/README.md new file mode 100644 index 0000000000..d0bcbadcae --- /dev/null +++ b/avm/res/compute/virtual-machine-scale-set/README.md @@ -0,0 +1,2504 @@ +# Virtual Machine Scale Sets `[Microsoft.Compute/virtualMachineScaleSets]` + +This module deploys a Virtual Machine Scale Set. + +## Navigation + +- [Resource Types](#Resource-Types) +- [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` | [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.Compute/virtualMachineScaleSets` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Compute/2022-11-01/virtualMachineScaleSets) | +| `Microsoft.Compute/virtualMachineScaleSets/extensions` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Compute/2022-11-01/virtualMachineScaleSets/extensions) | +| `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) | + +## 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/res/compute/virtual-machine-scale-set:`. + +- [Using only defaults for Linux](#example-1-using-only-defaults-for-linux) +- [Using large parameter set for Linux](#example-2-using-large-parameter-set-for-linux) +- [Using disk encryption set for the VM.](#example-3-using-disk-encryption-set-for-the-vm) +- [Using only defaults for Windows](#example-4-using-only-defaults-for-windows) +- [Using large parameter set for Windows](#example-5-using-large-parameter-set-for-windows) +- [WAF-aligned](#example-6-waf-aligned) + +### Example 1: _Using only defaults for Linux_ + +This instance deploys the module with the minimum set of required parameters. + + +

+ +via Bicep module + +```bicep +module virtualMachineScaleSet 'br/public:avm/res/compute/virtual-machine-scale-set:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-cvmsslinmin' + params: { + // Required parameters + adminUsername: 'scaleSetAdmin' + imageReference: { + offer: '0001-com-ubuntu-server-jammy' + publisher: 'Canonical' + sku: '22_04-lts-gen2' + version: 'latest' + } + name: 'cvmsslinmin001' + osDisk: { + createOption: 'fromImage' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Linux' + skuName: 'Standard_B12ms' + // Non-required parameters + disablePasswordAuthentication: true + location: '' + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig1' + properties: { + subnet: { + id: '' + } + } + } + ] + nicSuffix: '-nic01' + } + ] + publicKeys: [ + { + keyData: '' + path: '/home/scaleSetAdmin/.ssh/authorized_keys' + } + ] + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "adminUsername": { + "value": "scaleSetAdmin" + }, + "imageReference": { + "value": { + "offer": "0001-com-ubuntu-server-jammy", + "publisher": "Canonical", + "sku": "22_04-lts-gen2", + "version": "latest" + } + }, + "name": { + "value": "cvmsslinmin001" + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "osType": { + "value": "Linux" + }, + "skuName": { + "value": "Standard_B12ms" + }, + // Non-required parameters + "disablePasswordAuthentication": { + "value": true + }, + "location": { + "value": "" + }, + "nicConfigurations": { + "value": [ + { + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "subnet": { + "id": "" + } + } + } + ], + "nicSuffix": "-nic01" + } + ] + }, + "publicKeys": { + "value": [ + { + "keyData": "", + "path": "/home/scaleSetAdmin/.ssh/authorized_keys" + } + ] + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module virtualMachineScaleSet 'br/public:avm/res/compute/virtual-machine-scale-set:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-cvmsslinmax' + params: { + // Required parameters + adminUsername: 'scaleSetAdmin' + imageReference: { + offer: '0001-com-ubuntu-server-jammy' + publisher: 'Canonical' + sku: '22_04-lts-gen2' + version: 'latest' + } + name: 'cvmsslinmax001' + osDisk: { + createOption: 'fromImage' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Linux' + skuName: 'Standard_B12ms' + // Non-required parameters + availabilityZones: [ + '2' + ] + bootDiagnosticStorageAccountName: '' + dataDisks: [ + { + caching: 'ReadOnly' + createOption: 'Empty' + diskSizeGB: '256' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + { + caching: 'ReadOnly' + createOption: 'Empty' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + ] + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + disablePasswordAuthentication: true + encryptionAtHost: false + extensionAzureDiskEncryptionConfig: { + enabled: true + settings: { + EncryptionOperation: 'EnableEncryption' + KekVaultResourceId: '' + KeyEncryptionAlgorithm: 'RSA-OAEP' + KeyEncryptionKeyURL: '' + KeyVaultResourceId: '' + KeyVaultURL: '' + ResizeOSDisk: 'false' + VolumeType: 'All' + } + } + extensionCustomScriptConfig: { + enabled: true + fileData: [ + { + storageAccountId: '' + uri: '' + } + ] + protectedSettings: { + commandToExecute: 'sudo apt-get update' + } + } + extensionDependencyAgentConfig: { + enabled: true + } + extensionMonitoringAgentConfig: { + enabled: true + } + extensionNetworkWatcherAgentConfig: { + enabled: true + } + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + '' + ] + } + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig1' + properties: { + subnet: { + id: '' + } + } + } + ] + nicSuffix: '-nic01' + } + ] + publicKeys: [ + { + keyData: '' + path: '/home/scaleSetAdmin/.ssh/authorized_keys' + } + ] + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + scaleSetFaultDomain: 1 + skuCapacity: 1 + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + upgradePolicyMode: 'Manual' + vmNamePrefix: 'vmsslinvm' + vmPriority: 'Regular' + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "adminUsername": { + "value": "scaleSetAdmin" + }, + "imageReference": { + "value": { + "offer": "0001-com-ubuntu-server-jammy", + "publisher": "Canonical", + "sku": "22_04-lts-gen2", + "version": "latest" + } + }, + "name": { + "value": "cvmsslinmax001" + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "osType": { + "value": "Linux" + }, + "skuName": { + "value": "Standard_B12ms" + }, + // Non-required parameters + "availabilityZones": { + "value": [ + "2" + ] + }, + "bootDiagnosticStorageAccountName": { + "value": "" + }, + "dataDisks": { + "value": [ + { + "caching": "ReadOnly", + "createOption": "Empty", + "diskSizeGB": "256", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + }, + { + "caching": "ReadOnly", + "createOption": "Empty", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + ] + }, + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "disablePasswordAuthentication": { + "value": true + }, + "encryptionAtHost": { + "value": false + }, + "extensionAzureDiskEncryptionConfig": { + "value": { + "enabled": true, + "settings": { + "EncryptionOperation": "EnableEncryption", + "KekVaultResourceId": "", + "KeyEncryptionAlgorithm": "RSA-OAEP", + "KeyEncryptionKeyURL": "", + "KeyVaultResourceId": "", + "KeyVaultURL": "", + "ResizeOSDisk": "false", + "VolumeType": "All" + } + } + }, + "extensionCustomScriptConfig": { + "value": { + "enabled": true, + "fileData": [ + { + "storageAccountId": "", + "uri": "" + } + ], + "protectedSettings": { + "commandToExecute": "sudo apt-get update" + } + } + }, + "extensionDependencyAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionMonitoringAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionNetworkWatcherAgentConfig": { + "value": { + "enabled": true + } + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "managedIdentities": { + "value": { + "systemAssigned": true, + "userAssignedResourceIds": [ + "" + ] + } + }, + "nicConfigurations": { + "value": [ + { + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "subnet": { + "id": "" + } + } + } + ], + "nicSuffix": "-nic01" + } + ] + }, + "publicKeys": { + "value": [ + { + "keyData": "", + "path": "/home/scaleSetAdmin/.ssh/authorized_keys" + } + ] + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ] + }, + "scaleSetFaultDomain": { + "value": 1 + }, + "skuCapacity": { + "value": 1 + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + "upgradePolicyMode": { + "value": "Manual" + }, + "vmNamePrefix": { + "value": "vmsslinvm" + }, + "vmPriority": { + "value": "Regular" + } + } +} +``` + +
+

+ +### Example 3: _Using disk encryption set for the VM._ + +This instance deploys the module with disk enryption set. + + +

+ +via Bicep module + +```bicep +module virtualMachineScaleSet 'br/public:avm/res/compute/virtual-machine-scale-set:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-cvmsslcmk' + params: { + // Required parameters + adminUsername: 'scaleSetAdmin' + imageReference: { + offer: '0001-com-ubuntu-server-jammy' + publisher: 'Canonical' + sku: '22_04-lts-gen2' + version: 'latest' + } + name: 'cvmsslcmk001' + osDisk: { + createOption: 'fromImage' + diskSizeGB: '128' + managedDisk: { + diskEncryptionSet: { + id: '' + } + storageAccountType: 'Premium_LRS' + } + } + osType: 'Linux' + skuName: 'Standard_B12ms' + // Non-required parameters + dataDisks: [ + { + caching: 'ReadOnly' + createOption: 'Empty' + diskSizeGB: '128' + managedDisk: { + diskEncryptionSet: { + id: '' + } + storageAccountType: 'Premium_LRS' + } + } + ] + disablePasswordAuthentication: true + extensionMonitoringAgentConfig: { + enabled: true + } + location: '' + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig1' + properties: { + subnet: { + id: '' + } + } + } + ] + nicSuffix: '-nic01' + } + ] + publicKeys: [ + { + keyData: '' + path: '/home/scaleSetAdmin/.ssh/authorized_keys' + } + ] + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "adminUsername": { + "value": "scaleSetAdmin" + }, + "imageReference": { + "value": { + "offer": "0001-com-ubuntu-server-jammy", + "publisher": "Canonical", + "sku": "22_04-lts-gen2", + "version": "latest" + } + }, + "name": { + "value": "cvmsslcmk001" + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "diskSizeGB": "128", + "managedDisk": { + "diskEncryptionSet": { + "id": "" + }, + "storageAccountType": "Premium_LRS" + } + } + }, + "osType": { + "value": "Linux" + }, + "skuName": { + "value": "Standard_B12ms" + }, + // Non-required parameters + "dataDisks": { + "value": [ + { + "caching": "ReadOnly", + "createOption": "Empty", + "diskSizeGB": "128", + "managedDisk": { + "diskEncryptionSet": { + "id": "" + }, + "storageAccountType": "Premium_LRS" + } + } + ] + }, + "disablePasswordAuthentication": { + "value": true + }, + "extensionMonitoringAgentConfig": { + "value": { + "enabled": true + } + }, + "location": { + "value": "" + }, + "nicConfigurations": { + "value": [ + { + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "subnet": { + "id": "" + } + } + } + ], + "nicSuffix": "-nic01" + } + ] + }, + "publicKeys": { + "value": [ + { + "keyData": "", + "path": "/home/scaleSetAdmin/.ssh/authorized_keys" + } + ] + } + } +} +``` + +
+

+ +### Example 4: _Using only defaults for Windows_ + +This instance deploys the module with the minimum set of required parameters. + + +

+ +via Bicep module + +```bicep +module virtualMachineScaleSet 'br/public:avm/res/compute/virtual-machine-scale-set:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-cvmsswinmin' + params: { + // Required parameters + adminUsername: 'localAdminUser' + imageReference: { + offer: 'WindowsServer' + publisher: 'MicrosoftWindowsServer' + sku: '2022-datacenter-azure-edition' + version: 'latest' + } + name: 'cvmsswinmin001' + osDisk: { + createOption: 'fromImage' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Windows' + skuName: 'Standard_B12ms' + // Non-required parameters + adminPassword: '' + location: '' + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig1' + properties: { + subnet: { + id: '' + } + } + } + ] + nicSuffix: '-nic01' + } + ] + } +} +``` + +
+

+ +

+ +via JSON Parameter 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": "cvmsswinmin001" + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "osType": { + "value": "Windows" + }, + "skuName": { + "value": "Standard_B12ms" + }, + // Non-required parameters + "adminPassword": { + "value": "" + }, + "location": { + "value": "" + }, + "nicConfigurations": { + "value": [ + { + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "subnet": { + "id": "" + } + } + } + ], + "nicSuffix": "-nic01" + } + ] + } + } +} +``` + +
+

+ +### Example 5: _Using large parameter set for Windows_ + +This instance deploys the module with most of its features enabled. + + +

+ +via Bicep module + +```bicep +module virtualMachineScaleSet 'br/public:avm/res/compute/virtual-machine-scale-set:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-cvmsswinmax' + params: { + // Required parameters + adminUsername: 'localAdminUser' + imageReference: { + offer: 'WindowsServer' + publisher: 'MicrosoftWindowsServer' + sku: '2022-datacenter-azure-edition' + version: 'latest' + } + name: 'cvmsswinmax001' + osDisk: { + createOption: 'fromImage' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Windows' + skuName: 'Standard_B12ms' + // Non-required parameters + adminPassword: '' + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + encryptionAtHost: false + extensionAntiMalwareConfig: { + enabled: true + settings: { + AntimalwareEnabled: true + Exclusions: { + Extensions: '.log;.ldf' + Paths: 'D:\\IISlogs;D:\\DatabaseLogs' + Processes: 'mssence.svc' + } + RealtimeProtectionEnabled: true + ScheduledScanSettings: { + day: '7' + isEnabled: 'true' + scanType: 'Quick' + time: '120' + } + } + } + extensionAzureDiskEncryptionConfig: { + enabled: true + settings: { + EncryptionOperation: 'EnableEncryption' + KekVaultResourceId: '' + KeyEncryptionAlgorithm: 'RSA-OAEP' + KeyEncryptionKeyURL: '' + KeyVaultResourceId: '' + KeyVaultURL: '' + ResizeOSDisk: 'false' + VolumeType: 'All' + } + } + extensionCustomScriptConfig: { + enabled: true + fileData: [ + { + storageAccountId: '' + uri: '' + } + ] + protectedSettings: { + commandToExecute: '' + } + } + extensionDependencyAgentConfig: { + enabled: true + } + extensionDSCConfig: { + enabled: true + } + extensionMonitoringAgentConfig: { + enabled: true + } + extensionNetworkWatcherAgentConfig: { + enabled: true + } + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + '' + ] + } + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig1' + properties: { + subnet: { + id: '' + } + } + } + ] + nicSuffix: '-nic01' + } + ] + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + skuCapacity: 1 + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + upgradePolicyMode: 'Manual' + vmNamePrefix: 'vmsswinvm' + vmPriority: 'Regular' + } +} +``` + +
+

+ +

+ +via JSON Parameter 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": "cvmsswinmax001" + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "osType": { + "value": "Windows" + }, + "skuName": { + "value": "Standard_B12ms" + }, + // Non-required parameters + "adminPassword": { + "value": "" + }, + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "encryptionAtHost": { + "value": false + }, + "extensionAntiMalwareConfig": { + "value": { + "enabled": true, + "settings": { + "AntimalwareEnabled": true, + "Exclusions": { + "Extensions": ".log;.ldf", + "Paths": "D:\\IISlogs;D:\\DatabaseLogs", + "Processes": "mssence.svc" + }, + "RealtimeProtectionEnabled": true, + "ScheduledScanSettings": { + "day": "7", + "isEnabled": "true", + "scanType": "Quick", + "time": "120" + } + } + } + }, + "extensionAzureDiskEncryptionConfig": { + "value": { + "enabled": true, + "settings": { + "EncryptionOperation": "EnableEncryption", + "KekVaultResourceId": "", + "KeyEncryptionAlgorithm": "RSA-OAEP", + "KeyEncryptionKeyURL": "", + "KeyVaultResourceId": "", + "KeyVaultURL": "", + "ResizeOSDisk": "false", + "VolumeType": "All" + } + } + }, + "extensionCustomScriptConfig": { + "value": { + "enabled": true, + "fileData": [ + { + "storageAccountId": "", + "uri": "" + } + ], + "protectedSettings": { + "commandToExecute": "" + } + } + }, + "extensionDependencyAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionDSCConfig": { + "value": { + "enabled": true + } + }, + "extensionMonitoringAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionNetworkWatcherAgentConfig": { + "value": { + "enabled": true + } + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "managedIdentities": { + "value": { + "systemAssigned": true, + "userAssignedResourceIds": [ + "" + ] + } + }, + "nicConfigurations": { + "value": [ + { + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "subnet": { + "id": "" + } + } + } + ], + "nicSuffix": "-nic01" + } + ] + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ] + }, + "skuCapacity": { + "value": 1 + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + "upgradePolicyMode": { + "value": "Manual" + }, + "vmNamePrefix": { + "value": "vmsswinvm" + }, + "vmPriority": { + "value": "Regular" + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module virtualMachineScaleSet 'br/public:avm/res/compute/virtual-machine-scale-set:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-cvmsswinwaf' + params: { + // Required parameters + adminUsername: 'localAdminUser' + imageReference: { + offer: 'WindowsServer' + publisher: 'MicrosoftWindowsServer' + sku: '2022-datacenter-azure-edition' + version: 'latest' + } + name: 'cvmsswinwaf001' + osDisk: { + createOption: 'fromImage' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Windows' + skuName: 'Standard_B12ms' + // Non-required parameters + adminPassword: '' + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + encryptionAtHost: '' + extensionAntiMalwareConfig: { + enabled: true + settings: { + AntimalwareEnabled: true + Exclusions: { + Extensions: '.log;.ldf' + Paths: 'D:\\IISlogs;D:\\DatabaseLogs' + Processes: 'mssence.svc' + } + RealtimeProtectionEnabled: true + ScheduledScanSettings: { + day: '7' + isEnabled: 'true' + scanType: 'Quick' + time: '120' + } + } + } + extensionAzureDiskEncryptionConfig: { + enabled: true + settings: { + EncryptionOperation: 'EnableEncryption' + KekVaultResourceId: '' + KeyEncryptionAlgorithm: 'RSA-OAEP' + KeyEncryptionKeyURL: '' + KeyVaultResourceId: '' + KeyVaultURL: '' + ResizeOSDisk: 'false' + VolumeType: 'All' + } + } + extensionCustomScriptConfig: { + enabled: true + fileData: [ + { + storageAccountId: '' + uri: '' + } + ] + protectedSettings: { + commandToExecute: '' + } + } + extensionDependencyAgentConfig: { + enabled: true + } + extensionDSCConfig: { + enabled: true + } + extensionMonitoringAgentConfig: { + enabled: true + } + extensionNetworkWatcherAgentConfig: { + enabled: true + } + location: '' + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + '' + ] + } + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig1' + properties: { + subnet: { + id: '' + } + } + } + ] + nicSuffix: '-nic01' + } + ] + skuCapacity: 1 + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + upgradePolicyMode: 'Manual' + vmNamePrefix: 'vmsswinvm' + vmPriority: 'Regular' + } +} +``` + +
+

+ +

+ +via JSON Parameter 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": "cvmsswinwaf001" + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "osType": { + "value": "Windows" + }, + "skuName": { + "value": "Standard_B12ms" + }, + // Non-required parameters + "adminPassword": { + "value": "" + }, + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "encryptionAtHost": { + "value": "" + }, + "extensionAntiMalwareConfig": { + "value": { + "enabled": true, + "settings": { + "AntimalwareEnabled": true, + "Exclusions": { + "Extensions": ".log;.ldf", + "Paths": "D:\\IISlogs;D:\\DatabaseLogs", + "Processes": "mssence.svc" + }, + "RealtimeProtectionEnabled": true, + "ScheduledScanSettings": { + "day": "7", + "isEnabled": "true", + "scanType": "Quick", + "time": "120" + } + } + } + }, + "extensionAzureDiskEncryptionConfig": { + "value": { + "enabled": true, + "settings": { + "EncryptionOperation": "EnableEncryption", + "KekVaultResourceId": "", + "KeyEncryptionAlgorithm": "RSA-OAEP", + "KeyEncryptionKeyURL": "", + "KeyVaultResourceId": "", + "KeyVaultURL": "", + "ResizeOSDisk": "false", + "VolumeType": "All" + } + } + }, + "extensionCustomScriptConfig": { + "value": { + "enabled": true, + "fileData": [ + { + "storageAccountId": "", + "uri": "" + } + ], + "protectedSettings": { + "commandToExecute": "" + } + } + }, + "extensionDependencyAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionDSCConfig": { + "value": { + "enabled": true + } + }, + "extensionMonitoringAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionNetworkWatcherAgentConfig": { + "value": { + "enabled": true + } + }, + "location": { + "value": "" + }, + "managedIdentities": { + "value": { + "systemAssigned": true, + "userAssignedResourceIds": [ + "" + ] + } + }, + "nicConfigurations": { + "value": [ + { + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "subnet": { + "id": "" + } + } + } + ], + "nicSuffix": "-nic01" + } + ] + }, + "skuCapacity": { + "value": 1 + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + "upgradePolicyMode": { + "value": "Manual" + }, + "vmNamePrefix": { + "value": "vmsswinvm" + }, + "vmPriority": { + "value": "Regular" + } + } +} +``` + +
+

+ + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`adminUsername`](#parameter-adminusername) | securestring | Administrator username. | +| [`imageReference`](#parameter-imagereference) | object | OS image reference. In case of marketplace images, it's the combination of the publisher, offer, sku, version attributes. In case of custom images it's the resource ID of the custom image. | +| [`name`](#parameter-name) | string | Name of the VMSS. | +| [`nicConfigurations`](#parameter-nicconfigurations) | array | Configures NICs and PIPs. | +| [`osDisk`](#parameter-osdisk) | object | Specifies the OS disk. For security reasons, it is recommended to specify DiskEncryptionSet into the osDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VM Scale sets. | +| [`osType`](#parameter-ostype) | string | The chosen OS type. | +| [`skuName`](#parameter-skuname) | string | The SKU size of the VMs. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`additionalUnattendContent`](#parameter-additionalunattendcontent) | array | Specifies additional base-64 encoded XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. - AdditionalUnattendContent object. | +| [`adminPassword`](#parameter-adminpassword) | securestring | When specifying a Windows Virtual Machine, this value should be passed. | +| [`automaticRepairsPolicyEnabled`](#parameter-automaticrepairspolicyenabled) | bool | Specifies whether automatic repairs should be enabled on the virtual machine scale set. | +| [`availabilityZones`](#parameter-availabilityzones) | array | The virtual machine scale set zones. NOTE: Availability zones can only be set when you create the scale set. | +| [`bootDiagnosticStorageAccountName`](#parameter-bootdiagnosticstorageaccountname) | string | Storage account used to store boot diagnostic information. Boot diagnostics will be disabled if no value is provided. | +| [`bootDiagnosticStorageAccountUri`](#parameter-bootdiagnosticstorageaccounturi) | string | Storage account boot diagnostic base URI. | +| [`customData`](#parameter-customdata) | string | Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format. | +| [`dataDisks`](#parameter-datadisks) | array | Specifies the data disks. For security reasons, it is recommended to specify DiskEncryptionSet into the dataDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VM Scale sets. | +| [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | +| [`disableAutomaticRollback`](#parameter-disableautomaticrollback) | bool | Whether OS image rollback feature should be disabled. | +| [`disablePasswordAuthentication`](#parameter-disablepasswordauthentication) | bool | Specifies whether password authentication should be disabled. | +| [`doNotRunExtensionsOnOverprovisionedVMs`](#parameter-donotrunextensionsonoverprovisionedvms) | bool | When Overprovision is enabled, extensions are launched only on the requested number of VMs which are finally kept. This property will hence ensure that the extensions do not run on the extra overprovisioned VMs. | +| [`enableAutomaticOSUpgrade`](#parameter-enableautomaticosupgrade) | bool | Indicates whether OS upgrades should automatically be applied to scale set instances in a rolling fashion when a newer version of the OS image becomes available. Default value is false. If this is set to true for Windows based scale sets, enableAutomaticUpdates is automatically set to false and cannot be set to true. | +| [`enableAutomaticUpdates`](#parameter-enableautomaticupdates) | bool | Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning. | +| [`enableEvictionPolicy`](#parameter-enableevictionpolicy) | bool | Specifies the eviction policy for the low priority virtual machine. Will result in 'Deallocate' eviction policy. | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`encryptionAtHost`](#parameter-encryptionathost) | 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. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your virtual machine scale sets. | +| [`extensionAntiMalwareConfig`](#parameter-extensionantimalwareconfig) | object | The configuration for the [Anti Malware] extension. Must at least contain the ["enabled": true] property to be executed. | +| [`extensionAzureDiskEncryptionConfig`](#parameter-extensionazurediskencryptionconfig) | object | The configuration for the [Azure Disk Encryption] extension. Must at least contain the ["enabled": true] property to be executed. Restrictions: Cannot be enabled on disks that have encryption at host enabled. Managed disks encrypted using Azure Disk Encryption cannot be encrypted using customer-managed keys. | +| [`extensionCustomScriptConfig`](#parameter-extensioncustomscriptconfig) | object | The configuration for the [Custom Script] extension. Must at least contain the ["enabled": true] property to be executed. | +| [`extensionDependencyAgentConfig`](#parameter-extensiondependencyagentconfig) | object | The configuration for the [Dependency Agent] extension. Must at least contain the ["enabled": true] property to be executed. | +| [`extensionDomainJoinConfig`](#parameter-extensiondomainjoinconfig) | object | The configuration for the [Domain Join] extension. Must at least contain the ["enabled": true] property to be executed. | +| [`extensionDomainJoinPassword`](#parameter-extensiondomainjoinpassword) | securestring | Required if name is specified. Password of the user specified in user parameter. | +| [`extensionDSCConfig`](#parameter-extensiondscconfig) | object | The configuration for the [Desired State Configuration] extension. Must at least contain the ["enabled": true] property to be executed. | +| [`extensionMonitoringAgentConfig`](#parameter-extensionmonitoringagentconfig) | object | The configuration for the [Monitoring Agent] extension. Must at least contain the ["enabled": true] property to be executed. | +| [`extensionNetworkWatcherAgentConfig`](#parameter-extensionnetworkwatcheragentconfig) | object | The configuration for the [Network Watcher Agent] extension. Must at least contain the ["enabled": true] property to be executed. | +| [`gracePeriod`](#parameter-graceperiod) | string | The amount of time for which automatic repairs are suspended due to a state change on VM. The grace time starts after the state change has completed. This helps avoid premature or accidental repairs. The time duration should be specified in ISO 8601 format. The minimum allowed grace period is 30 minutes (PT30M). The maximum allowed grace period is 90 minutes (PT90M). | +| [`licenseType`](#parameter-licensetype) | string | Specifies that the image or disk that is being used was licensed on-premises. This element is only used for images that contain the Windows Server operating system. | +| [`location`](#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. | +| [`maxBatchInstancePercent`](#parameter-maxbatchinstancepercent) | int | The maximum percent of total virtual machine instances that will be upgraded simultaneously by the rolling upgrade in one batch. As this is a maximum, unhealthy instances in previous or future batches can cause the percentage of instances in a batch to decrease to ensure higher reliability. | +| [`maxPriceForLowPriorityVm`](#parameter-maxpriceforlowpriorityvm) | string | Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars. | +| [`maxUnhealthyInstancePercent`](#parameter-maxunhealthyinstancepercent) | int | The maximum percentage of the total virtual machine instances in the scale set that can be simultaneously unhealthy, either as a result of being upgraded, or by being found in an unhealthy state by the virtual machine health checks before the rolling upgrade aborts. This constraint will be checked prior to starting any batch. | +| [`maxUnhealthyUpgradedInstancePercent`](#parameter-maxunhealthyupgradedinstancepercent) | int | The maximum percentage of the total virtual machine instances in the scale set that can be simultaneously unhealthy, either as a result of being upgraded, or by being found in an unhealthy state by the virtual machine health checks before the rolling upgrade aborts. This constraint will be checked prior to starting any batch. | +| [`monitoringWorkspaceId`](#parameter-monitoringworkspaceid) | string | Resource ID of the monitoring log analytics workspace. | +| [`overprovision`](#parameter-overprovision) | bool | Specifies whether the Virtual Machine Scale Set should be overprovisioned. | +| [`pauseTimeBetweenBatches`](#parameter-pausetimebetweenbatches) | string | The wait time between completing the update for all virtual machines in one batch and starting the next batch. The time duration should be specified in ISO 8601 format. | +| [`plan`](#parameter-plan) | object | Specifies information about the marketplace image used to create the virtual machine. This element is only used for marketplace images. Before you can use a marketplace image from an API, you must enable the image for programmatic use. | +| [`provisionVMAgent`](#parameter-provisionvmagent) | bool | Indicates whether virtual machine agent should be provisioned on the virtual machine. When this property is not specified in the request body, default behavior is to set it to true. This will ensure that VM Agent is installed on the VM so that extensions can be added to the VM later. | +| [`proximityPlacementGroupResourceId`](#parameter-proximityplacementgroupresourceid) | string | Resource ID of a proximity placement group. | +| [`publicKeys`](#parameter-publickeys) | array | The list of SSH public keys used to authenticate with linux based VMs. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`sasTokenValidityLength`](#parameter-sastokenvaliditylength) | string | SAS token validity length to use to download files from storage accounts. Usage: 'PT8H' - valid for 8 hours; 'P5D' - valid for 5 days; 'P1Y' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours. | +| [`scaleInPolicy`](#parameter-scaleinpolicy) | object | Specifies the scale-in policy that decides which virtual machines are chosen for removal when a Virtual Machine Scale Set is scaled-in. | +| [`scaleSetFaultDomain`](#parameter-scalesetfaultdomain) | int | Fault Domain count for each placement group. | +| [`scheduledEventsProfile`](#parameter-scheduledeventsprofile) | object | Specifies Scheduled Event related configurations. | +| [`secrets`](#parameter-secrets) | array | Specifies set of certificates that should be installed onto the virtual machines in the scale set. | +| [`secureBootEnabled`](#parameter-securebootenabled) | bool | Specifies whether secure boot should be enabled on the virtual machine scale set. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings. | +| [`securityType`](#parameter-securitytype) | string | Specifies the SecurityType of the virtual machine scale set. It is set as TrustedLaunch to enable UefiSettings. | +| [`singlePlacementGroup`](#parameter-singleplacementgroup) | bool | When true this limits the scale set to a single placement group, of max size 100 virtual machines. NOTE: If singlePlacementGroup is true, it may be modified to false. However, if singlePlacementGroup is false, it may not be modified to true. | +| [`skuCapacity`](#parameter-skucapacity) | int | The initial instance count of scale set VMs. | +| [`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. | +| [`upgradePolicyMode`](#parameter-upgradepolicymode) | string | Specifies the mode of an upgrade to virtual machines in the scale set.' Manual - You control the application of updates to virtual machines in the scale set. You do this by using the manualUpgrade action. ; Automatic - All virtual machines in the scale set are automatically updated at the same time. - Automatic, Manual, Rolling. | +| [`vmNamePrefix`](#parameter-vmnameprefix) | string | Specifies the computer name prefix for all of the virtual machines in the scale set. | +| [`vmPriority`](#parameter-vmpriority) | string | Specifies the priority for the virtual machine. | +| [`vTpmEnabled`](#parameter-vtpmenabled) | bool | Specifies whether vTPM should be enabled on the virtual machine scale set. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings. | +| [`winRM`](#parameter-winrm) | object | Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object. | +| [`zoneBalance`](#parameter-zonebalance) | bool | Whether to force strictly even Virtual Machine distribution cross x-zones in case there is zone outage. | + +**Generated parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`baseTime`](#parameter-basetime) | string | Do not provide a value! This date value is used to generate a registration token. | + +### Parameter: `adminUsername` + +Administrator username. + +- Required: Yes +- Type: securestring + +### Parameter: `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: Yes +- Type: object + +### Parameter: `name` + +Name of the VMSS. + +- Required: Yes +- Type: string + +### Parameter: `nicConfigurations` + +Configures NICs and PIPs. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `osDisk` + +Specifies the OS disk. For security reasons, it is recommended to specify DiskEncryptionSet into the osDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VM Scale sets. + +- Required: Yes +- Type: object + +### Parameter: `osType` + +The chosen OS type. + +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'Linux' + 'Windows' + ] + ``` + +### Parameter: `skuName` + +The SKU size of the VMs. + +- Required: Yes +- Type: string + +### Parameter: `additionalUnattendContent` + +Specifies additional base-64 encoded XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. - AdditionalUnattendContent object. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `adminPassword` + +When specifying a Windows Virtual Machine, this value should be passed. + +- Required: No +- Type: securestring +- Default: `''` + +### Parameter: `automaticRepairsPolicyEnabled` + +Specifies whether automatic repairs should be enabled on the virtual machine scale set. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `availabilityZones` + +The virtual machine scale set zones. NOTE: Availability zones can only be set when you create the scale set. + +- Required: No +- Type: array +- Default: + ```Bicep + [ + 1 + 2 + 3 + ] + ``` + +### Parameter: `bootDiagnosticStorageAccountName` + +Storage account used to store boot diagnostic information. Boot diagnostics will be disabled if no value is provided. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `bootDiagnosticStorageAccountUri` + +Storage account boot diagnostic base URI. + +- Required: No +- Type: string +- Default: `[format('.blob.{0}/', environment().suffixes.storage)]` + +### Parameter: `customData` + +Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `dataDisks` + +Specifies the data disks. For security reasons, it is recommended to specify DiskEncryptionSet into the dataDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VM Scale sets. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `diagnosticSettings` + +The diagnostic settings of the service. + +- Required: No +- Type: array + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`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. | +| [`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. | +| [`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. | + +### Parameter: `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: `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: `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: `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: `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-diagnosticsettingsmetriccategoriescategory) | 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-diagnosticsettingsmetriccategoriesenabled) | bool | Enable or disable the category explicitly. Default is `true`. | + +### Parameter: `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: `diagnosticSettings.metricCategories.enabled` + +Enable or disable the category explicitly. Default is `true`. + +- Required: No +- Type: bool + +### Parameter: `diagnosticSettings.name` + +The name of diagnostic setting. + +- Required: No +- Type: string + +### Parameter: `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: `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: `disableAutomaticRollback` + +Whether OS image rollback feature should be disabled. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `disablePasswordAuthentication` + +Specifies whether password authentication should be disabled. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `doNotRunExtensionsOnOverprovisionedVMs` + +When Overprovision is enabled, extensions are launched only on the requested number of VMs which are finally kept. This property will hence ensure that the extensions do not run on the extra overprovisioned VMs. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `enableAutomaticOSUpgrade` + +Indicates whether OS upgrades should automatically be applied to scale set instances in a rolling fashion when a newer version of the OS image becomes available. Default value is false. If this is set to true for Windows based scale sets, enableAutomaticUpdates is automatically set to false and cannot be set to true. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `enableAutomaticUpdates` + +Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `enableEvictionPolicy` + +Specifies the eviction policy for the low priority virtual machine. Will result in 'Deallocate' eviction policy. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `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. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your virtual machine scale sets. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `extensionAntiMalwareConfig` + +The configuration for the [Anti Malware] extension. Must at least contain the ["enabled": true] property to be executed. + +- Required: No +- Type: object +- Default: + ```Bicep + { + enabled: false + } + ``` + +### Parameter: `extensionAzureDiskEncryptionConfig` + +The configuration for the [Azure Disk Encryption] extension. Must at least contain the ["enabled": true] property to be executed. Restrictions: Cannot be enabled on disks that have encryption at host enabled. Managed disks encrypted using Azure Disk Encryption cannot be encrypted using customer-managed keys. + +- Required: No +- Type: object +- Default: + ```Bicep + { + enabled: false + } + ``` + +### Parameter: `extensionCustomScriptConfig` + +The configuration for the [Custom Script] extension. Must at least contain the ["enabled": true] property to be executed. + +- Required: No +- Type: object +- Default: + ```Bicep + { + enabled: false + fileData: [] + } + ``` + +### Parameter: `extensionDependencyAgentConfig` + +The configuration for the [Dependency Agent] extension. Must at least contain the ["enabled": true] property to be executed. + +- Required: No +- Type: object +- Default: + ```Bicep + { + enabled: false + } + ``` + +### Parameter: `extensionDomainJoinConfig` + +The configuration for the [Domain Join] extension. Must at least contain the ["enabled": true] property to be executed. + +- Required: No +- Type: object +- Default: + ```Bicep + { + enabled: false + } + ``` + +### Parameter: `extensionDomainJoinPassword` + +Required if name is specified. Password of the user specified in user parameter. + +- Required: No +- Type: securestring +- Default: `''` + +### Parameter: `extensionDSCConfig` + +The configuration for the [Desired State Configuration] extension. Must at least contain the ["enabled": true] property to be executed. + +- Required: No +- Type: object +- Default: + ```Bicep + { + enabled: false + } + ``` + +### Parameter: `extensionMonitoringAgentConfig` + +The configuration for the [Monitoring Agent] extension. Must at least contain the ["enabled": true] property to be executed. + +- Required: No +- Type: object +- Default: + ```Bicep + { + enabled: false + } + ``` + +### Parameter: `extensionNetworkWatcherAgentConfig` + +The configuration for the [Network Watcher Agent] extension. Must at least contain the ["enabled": true] property to be executed. + +- Required: No +- Type: object +- Default: + ```Bicep + { + enabled: false + } + ``` + +### Parameter: `gracePeriod` + +The amount of time for which automatic repairs are suspended due to a state change on VM. The grace time starts after the state change has completed. This helps avoid premature or accidental repairs. The time duration should be specified in ISO 8601 format. The minimum allowed grace period is 30 minutes (PT30M). The maximum allowed grace period is 90 minutes (PT90M). + +- Required: No +- Type: string +- Default: `'PT30M'` + +### Parameter: `licenseType` + +Specifies that the image or disk that is being used was licensed on-premises. This element is only used for images that contain the Windows Server operating system. + +- Required: No +- Type: string +- Default: `''` +- Allowed: + ```Bicep + [ + '' + 'Windows_Client' + 'Windows_Server' + ] + ``` + +### 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. + +- 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. | + +### 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: No +- Type: array + +### Parameter: `maxBatchInstancePercent` + +The maximum percent of total virtual machine instances that will be upgraded simultaneously by the rolling upgrade in one batch. As this is a maximum, unhealthy instances in previous or future batches can cause the percentage of instances in a batch to decrease to ensure higher reliability. + +- Required: No +- Type: int +- Default: `20` + +### Parameter: `maxPriceForLowPriorityVm` + +Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `maxUnhealthyInstancePercent` + +The maximum percentage of the total virtual machine instances in the scale set that can be simultaneously unhealthy, either as a result of being upgraded, or by being found in an unhealthy state by the virtual machine health checks before the rolling upgrade aborts. This constraint will be checked prior to starting any batch. + +- Required: No +- Type: int +- Default: `20` + +### Parameter: `maxUnhealthyUpgradedInstancePercent` + +The maximum percentage of the total virtual machine instances in the scale set that can be simultaneously unhealthy, either as a result of being upgraded, or by being found in an unhealthy state by the virtual machine health checks before the rolling upgrade aborts. This constraint will be checked prior to starting any batch. + +- Required: No +- Type: int +- Default: `20` + +### Parameter: `monitoringWorkspaceId` + +Resource ID of the monitoring log analytics workspace. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `overprovision` + +Specifies whether the Virtual Machine Scale Set should be overprovisioned. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `pauseTimeBetweenBatches` + +The wait time between completing the update for all virtual machines in one batch and starting the next batch. The time duration should be specified in ISO 8601 format. + +- Required: No +- Type: string +- Default: `'PT0S'` + +### Parameter: `plan` + +Specifies information about the marketplace image used to create the virtual machine. This element is only used for marketplace images. Before you can use a marketplace image from an API, you must enable the image for programmatic use. + +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `provisionVMAgent` + +Indicates whether virtual machine agent should be provisioned on the virtual machine. When this property is not specified in the request body, default behavior is to set it to true. This will ensure that VM Agent is installed on the VM so that extensions can be added to the VM later. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `proximityPlacementGroupResourceId` + +Resource ID of a proximity placement group. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `publicKeys` + +The list of SSH public keys used to authenticate with linux based VMs. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**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. | +| [`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.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `sasTokenValidityLength` + +SAS token validity length to use to download files from storage accounts. Usage: 'PT8H' - valid for 8 hours; 'P5D' - valid for 5 days; 'P1Y' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours. + +- Required: No +- Type: string +- Default: `'PT8H'` + +### Parameter: `scaleInPolicy` + +Specifies the scale-in policy that decides which virtual machines are chosen for removal when a Virtual Machine Scale Set is scaled-in. + +- Required: No +- Type: object +- Default: + ```Bicep + { + rules: [ + 'Default' + ] + } + ``` + +### Parameter: `scaleSetFaultDomain` + +Fault Domain count for each placement group. + +- Required: No +- Type: int +- Default: `1` + +### Parameter: `scheduledEventsProfile` + +Specifies Scheduled Event related configurations. + +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `secrets` + +Specifies set of certificates that should be installed onto the virtual machines in the scale set. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `secureBootEnabled` + +Specifies whether secure boot should be enabled on the virtual machine scale set. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `securityType` + +Specifies the SecurityType of the virtual machine scale set. It is set as TrustedLaunch to enable UefiSettings. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `singlePlacementGroup` + +When true this limits the scale set to a single placement group, of max size 100 virtual machines. NOTE: If singlePlacementGroup is true, it may be modified to false. However, if singlePlacementGroup is false, it may not be modified to true. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `skuCapacity` + +The initial instance count of scale set VMs. + +- Required: No +- Type: int +- Default: `1` + +### Parameter: `tags` + +Tags of the resource. + +- Required: No +- Type: object + +### Parameter: `timeZone` + +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`. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `ultraSSDEnabled` + +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. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `upgradePolicyMode` + +Specifies the mode of an upgrade to virtual machines in the scale set.' Manual - You control the application of updates to virtual machines in the scale set. You do this by using the manualUpgrade action. ; Automatic - All virtual machines in the scale set are automatically updated at the same time. - Automatic, Manual, Rolling. + +- Required: No +- Type: string +- Default: `'Manual'` +- Allowed: + ```Bicep + [ + 'Automatic' + 'Manual' + 'Rolling' + ] + ``` + +### Parameter: `vmNamePrefix` + +Specifies the computer name prefix for all of the virtual machines in the scale set. + +- Required: No +- Type: string +- Default: `'vmssvm'` + +### Parameter: `vmPriority` + +Specifies the priority for the virtual machine. + +- Required: No +- Type: string +- Default: `'Regular'` +- Allowed: + ```Bicep + [ + 'Low' + 'Regular' + 'Spot' + ] + ``` + +### Parameter: `vTpmEnabled` + +Specifies whether vTPM should be enabled on the virtual machine scale set. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `winRM` + +Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object. + +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `zoneBalance` + +Whether to force strictly even Virtual Machine distribution cross x-zones in case there is zone outage. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `baseTime` + +Do not provide a value! This date value is used to generate a registration token. + +- Required: No +- Type: string +- Default: `[utcNow('u')]` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the virtual machine scale set. | +| `resourceGroupName` | string | The resource group of the virtual machine scale set. | +| `resourceId` | string | The resource ID of the virtual machine scale set. | +| `systemAssignedMIPrincipalId` | string | The principal ID of the system assigned identity. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/compute/virtual-machine-scale-set/extension/README.md b/avm/res/compute/virtual-machine-scale-set/extension/README.md new file mode 100644 index 0000000000..11e4e8c5ad --- /dev/null +++ b/avm/res/compute/virtual-machine-scale-set/extension/README.md @@ -0,0 +1,143 @@ +# Virtual Machine Scale Set Extensions `[Microsoft.Compute/virtualMachineScaleSets/extensions]` + +This module deploys a Virtual Machine Scale Set Extension. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Compute/virtualMachineScaleSets/extensions` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Compute/2022-11-01/virtualMachineScaleSets/extensions) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`autoUpgradeMinorVersion`](#parameter-autoupgrademinorversion) | bool | Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true. | +| [`enableAutomaticUpgrade`](#parameter-enableautomaticupgrade) | bool | Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available. | +| [`name`](#parameter-name) | string | The name of the virtual machine scale set extension. | +| [`publisher`](#parameter-publisher) | string | The name of the extension handler publisher. | +| [`type`](#parameter-type) | string | Specifies the type of the extension; an example is "CustomScriptExtension". | +| [`typeHandlerVersion`](#parameter-typehandlerversion) | string | Specifies the version of the script handler. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`virtualMachineScaleSetName`](#parameter-virtualmachinescalesetname) | string | The name of the parent virtual machine scale set that extension is provisioned for. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`forceUpdateTag`](#parameter-forceupdatetag) | string | How the extension handler should be forced to update even if the extension configuration has not changed. | +| [`protectedSettings`](#parameter-protectedsettings) | secureObject | Any object that contains the extension specific protected settings. | +| [`settings`](#parameter-settings) | object | Any object that contains the extension specific settings. | +| [`supressFailures`](#parameter-supressfailures) | bool | Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false. | + +### Parameter: `autoUpgradeMinorVersion` + +Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true. + +- Required: Yes +- Type: bool + +### Parameter: `enableAutomaticUpgrade` + +Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available. + +- Required: Yes +- Type: bool + +### Parameter: `name` + +The name of the virtual machine scale set extension. + +- Required: Yes +- Type: string + +### Parameter: `publisher` + +The name of the extension handler publisher. + +- Required: Yes +- Type: string + +### Parameter: `type` + +Specifies the type of the extension; an example is "CustomScriptExtension". + +- Required: Yes +- Type: string + +### Parameter: `typeHandlerVersion` + +Specifies the version of the script handler. + +- Required: Yes +- Type: string + +### Parameter: `virtualMachineScaleSetName` + +The name of the parent virtual machine scale set that extension is provisioned for. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `forceUpdateTag` + +How the extension handler should be forced to update even if the extension configuration has not changed. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `protectedSettings` + +Any object that contains the extension specific protected settings. + +- Required: No +- Type: secureObject +- Default: `{}` + +### Parameter: `settings` + +Any object that contains the extension specific settings. + +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `supressFailures` + +Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false. + +- Required: No +- Type: bool +- Default: `False` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the extension. | +| `resourceGroupName` | string | The name of the Resource Group the extension was created in. | +| `resourceId` | string | The ResourceId of the extension. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/compute/virtual-machine-scale-set/extension/main.bicep b/avm/res/compute/virtual-machine-scale-set/extension/main.bicep new file mode 100644 index 0000000000..5f5074d008 --- /dev/null +++ b/avm/res/compute/virtual-machine-scale-set/extension/main.bicep @@ -0,0 +1,66 @@ +metadata name = 'Virtual Machine Scale Set Extensions' +metadata description = 'This module deploys a Virtual Machine Scale Set Extension.' +metadata owner = 'Azure/module-maintainers' + +@description('Conditional. The name of the parent virtual machine scale set that extension is provisioned for. Required if the template is used in a standalone deployment.') +param virtualMachineScaleSetName string + +@description('Required. The name of the virtual machine scale set extension.') +param name string + +@description('Required. The name of the extension handler publisher.') +param publisher string + +@description('Required. Specifies the type of the extension; an example is "CustomScriptExtension".') +param type string + +@description('Required. Specifies the version of the script handler.') +param typeHandlerVersion string + +@description('Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true.') +param autoUpgradeMinorVersion bool + +@description('Optional. How the extension handler should be forced to update even if the extension configuration has not changed.') +param forceUpdateTag string = '' + +@description('Optional. Any object that contains the extension specific settings.') +param settings object = {} + +@description('Optional. Any object that contains the extension specific protected settings.') +@secure() +param protectedSettings object = {} + +@description('Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false.') +param supressFailures bool = false + +@description('Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available.') +param enableAutomaticUpgrade bool + +resource virtualMachineScaleSet 'Microsoft.Compute/virtualMachineScaleSets@2022-11-01' existing = { + name: virtualMachineScaleSetName +} + +resource extension 'Microsoft.Compute/virtualMachineScaleSets/extensions@2022-11-01' = { + name: name + parent: virtualMachineScaleSet + properties: { + publisher: publisher + type: type + typeHandlerVersion: typeHandlerVersion + autoUpgradeMinorVersion: autoUpgradeMinorVersion + enableAutomaticUpgrade: enableAutomaticUpgrade + forceUpdateTag: !empty(forceUpdateTag) ? forceUpdateTag : null + settings: !empty(settings) ? settings : null + protectedSettings: !empty(protectedSettings) ? protectedSettings : null + suppressFailures: supressFailures + } +} + +@description('The name of the extension.') +output name string = extension.name + +@description('The ResourceId of the extension.') +output resourceId string = extension.id + +@description('The name of the Resource Group the extension was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/avm/res/compute/virtual-machine-scale-set/extension/main.json b/avm/res/compute/virtual-machine-scale-set/extension/main.json new file mode 100644 index 0000000000..36751fb40e --- /dev/null +++ b/avm/res/compute/virtual-machine-scale-set/extension/main.json @@ -0,0 +1,127 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "3680417048986934448" + }, + "name": "Virtual Machine Scale Set Extensions", + "description": "This module deploys a Virtual Machine Scale Set Extension.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "virtualMachineScaleSetName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent virtual machine scale set that extension is provisioned for. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine scale set extension." + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher." + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler." + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings." + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings." + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." + } + } + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachineScaleSets/extensions", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('virtualMachineScaleSetName'), parameters('name'))]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the extension." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The ResourceId of the extension." + }, + "value": "[resourceId('Microsoft.Compute/virtualMachineScaleSets/extensions', parameters('virtualMachineScaleSetName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/compute/virtual-machine-scale-set/main.bicep b/avm/res/compute/virtual-machine-scale-set/main.bicep new file mode 100644 index 0000000000..d9cdc509ca --- /dev/null +++ b/avm/res/compute/virtual-machine-scale-set/main.bicep @@ -0,0 +1,740 @@ +metadata name = 'Virtual Machine Scale Sets' +metadata description = 'This module deploys a Virtual Machine Scale Set.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. Name of the VMSS.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your virtual machine scale sets.') +param encryptionAtHost bool = true + +@description('Optional. Specifies the SecurityType of the virtual machine scale set. It is set as TrustedLaunch to enable UefiSettings.') +param securityType string = '' + +@description('Optional. Specifies whether secure boot should be enabled on the virtual machine scale set. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings.') +param secureBootEnabled bool = false + +@description('Optional. Specifies whether vTPM should be enabled on the virtual machine scale set. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings.') +param vTpmEnabled bool = false + +@description('Required. OS image reference. In case of marketplace images, it\'s the combination of the publisher, offer, sku, version attributes. In case of custom images it\'s the resource ID of the custom image.') +param imageReference object + +@description('Optional. Specifies information about the marketplace image used to create the virtual machine. This element is only used for marketplace images. Before you can use a marketplace image from an API, you must enable the image for programmatic use.') +param plan object = {} + +@description('Required. Specifies the OS disk. For security reasons, it is recommended to specify DiskEncryptionSet into the osDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VM Scale sets.') +param osDisk object + +@description('Optional. Specifies the data disks. For security reasons, it is recommended to specify DiskEncryptionSet into the dataDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VM Scale sets.') +param dataDisks array = [] + +@description('Optional. The flag that enables or disables a capability to have one or more managed data disks with UltraSSD_LRS storage account type on the VM or VMSS. Managed disks with storage account type UltraSSD_LRS can be added to a virtual machine or virtual machine scale set only if this property is enabled.') +param ultraSSDEnabled bool = false + +@description('Required. Administrator username.') +@secure() +param adminUsername string + +@description('Optional. When specifying a Windows Virtual Machine, this value should be passed.') +@secure() +param adminPassword string = '' + +@description('Optional. Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format.') +param customData string = '' + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +@description('Optional. Fault Domain count for each placement group.') +param scaleSetFaultDomain int = 1 + +@description('Optional. Resource ID of a proximity placement group.') +param proximityPlacementGroupResourceId string = '' + +@description('Required. Configures NICs and PIPs.') +param nicConfigurations array = [] + +@description('Optional. Specifies the priority for the virtual machine.') +@allowed([ + 'Regular' + 'Low' + 'Spot' +]) +param vmPriority string = 'Regular' + +@description('Optional. Specifies the eviction policy for the low priority virtual machine. Will result in \'Deallocate\' eviction policy.') +param enableEvictionPolicy bool = false + +@description('Optional. Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars.') +param maxPriceForLowPriorityVm string = '' + +@description('Optional. Specifies that the image or disk that is being used was licensed on-premises. This element is only used for images that contain the Windows Server operating system.') +@allowed([ + 'Windows_Client' + 'Windows_Server' + '' +]) +param licenseType string = '' + +@description('Optional. Required if name is specified. Password of the user specified in user parameter.') +@secure() +param extensionDomainJoinPassword string = '' + +@description('Optional. The configuration for the [Domain Join] extension. Must at least contain the ["enabled": true] property to be executed.') +param extensionDomainJoinConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Anti Malware] extension. Must at least contain the ["enabled": true] property to be executed.') +param extensionAntiMalwareConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Monitoring Agent] extension. Must at least contain the ["enabled": true] property to be executed.') +param extensionMonitoringAgentConfig object = { + enabled: false +} + +@description('Optional. Resource ID of the monitoring log analytics workspace.') +param monitoringWorkspaceId string = '' + +@description('Optional. The configuration for the [Dependency Agent] extension. Must at least contain the ["enabled": true] property to be executed.') +param extensionDependencyAgentConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Network Watcher Agent] extension. Must at least contain the ["enabled": true] property to be executed.') +param extensionNetworkWatcherAgentConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Azure Disk Encryption] extension. Must at least contain the ["enabled": true] property to be executed. Restrictions: Cannot be enabled on disks that have encryption at host enabled. Managed disks encrypted using Azure Disk Encryption cannot be encrypted using customer-managed keys.') +param extensionAzureDiskEncryptionConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Desired State Configuration] extension. Must at least contain the ["enabled": true] property to be executed.') +param extensionDSCConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Custom Script] extension. Must at least contain the ["enabled": true] property to be executed.') +param extensionCustomScriptConfig object = { + enabled: false + fileData: [] +} + +@description('Optional. Storage account boot diagnostic base URI.') +param bootDiagnosticStorageAccountUri string = '.blob.${environment().suffixes.storage}/' + +@description('Optional. Storage account used to store boot diagnostic information. Boot diagnostics will be disabled if no value is provided.') +param bootDiagnosticStorageAccountName string = '' + +@description('Optional. The diagnostic settings of the service.') +param diagnosticSettings diagnosticSettingType + +@description('Optional. The lock settings of the service.') +param lock lockType + +@description('Optional. Specifies the mode of an upgrade to virtual machines in the scale set.\' Manual - You control the application of updates to virtual machines in the scale set. You do this by using the manualUpgrade action. ; Automatic - All virtual machines in the scale set are automatically updated at the same time. - Automatic, Manual, Rolling.') +@allowed([ + 'Manual' + 'Automatic' + 'Rolling' +]) +param upgradePolicyMode string = 'Manual' + +@description('Optional. The maximum percent of total virtual machine instances that will be upgraded simultaneously by the rolling upgrade in one batch. As this is a maximum, unhealthy instances in previous or future batches can cause the percentage of instances in a batch to decrease to ensure higher reliability.') +param maxBatchInstancePercent int = 20 + +@description('Optional. The maximum percentage of the total virtual machine instances in the scale set that can be simultaneously unhealthy, either as a result of being upgraded, or by being found in an unhealthy state by the virtual machine health checks before the rolling upgrade aborts. This constraint will be checked prior to starting any batch.') +param maxUnhealthyInstancePercent int = 20 + +@description('Optional. The maximum percentage of the total virtual machine instances in the scale set that can be simultaneously unhealthy, either as a result of being upgraded, or by being found in an unhealthy state by the virtual machine health checks before the rolling upgrade aborts. This constraint will be checked prior to starting any batch.') +param maxUnhealthyUpgradedInstancePercent int = 20 + +@description('Optional. The wait time between completing the update for all virtual machines in one batch and starting the next batch. The time duration should be specified in ISO 8601 format.') +param pauseTimeBetweenBatches string = 'PT0S' + +@description('Optional. Indicates whether OS upgrades should automatically be applied to scale set instances in a rolling fashion when a newer version of the OS image becomes available. Default value is false. If this is set to true for Windows based scale sets, enableAutomaticUpdates is automatically set to false and cannot be set to true.') +param enableAutomaticOSUpgrade bool = false + +@description('Optional. Whether OS image rollback feature should be disabled.') +param disableAutomaticRollback bool = false + +@description('Optional. Specifies whether automatic repairs should be enabled on the virtual machine scale set.') +param automaticRepairsPolicyEnabled bool = false + +@description('Optional. The amount of time for which automatic repairs are suspended due to a state change on VM. The grace time starts after the state change has completed. This helps avoid premature or accidental repairs. The time duration should be specified in ISO 8601 format. The minimum allowed grace period is 30 minutes (PT30M). The maximum allowed grace period is 90 minutes (PT90M).') +param gracePeriod string = 'PT30M' + +@description('Optional. Specifies the computer name prefix for all of the virtual machines in the scale set.') +@minLength(1) +@maxLength(15) +param vmNamePrefix string = 'vmssvm' + +@description('Optional. Indicates whether virtual machine agent should be provisioned on the virtual machine. When this property is not specified in the request body, default behavior is to set it to true. This will ensure that VM Agent is installed on the VM so that extensions can be added to the VM later.') +param provisionVMAgent bool = true + +@description('Optional. Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning.') +param enableAutomaticUpdates bool = true + +@description('Optional. Specifies the time zone of the virtual machine. e.g. \'Pacific Standard Time\'. Possible values can be `TimeZoneInfo.id` value from time zones returned by `TimeZoneInfo.GetSystemTimeZones`.') +param timeZone string = '' + +@description('Optional. Specifies additional base-64 encoded XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. - AdditionalUnattendContent object.') +param additionalUnattendContent array = [] + +@description('Optional. Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object.') +param winRM object = {} + +@description('Optional. Specifies whether password authentication should be disabled.') +#disable-next-line secure-secrets-in-params // Not a secret +param disablePasswordAuthentication bool = false + +@description('Optional. The list of SSH public keys used to authenticate with linux based VMs.') +param publicKeys array = [] + +@description('Optional. Specifies set of certificates that should be installed onto the virtual machines in the scale set.') +#disable-next-line secure-secrets-in-params // Not a secret +param secrets array = [] + +@description('Optional. Specifies Scheduled Event related configurations.') +param scheduledEventsProfile object = {} + +@description('Optional. Specifies whether the Virtual Machine Scale Set should be overprovisioned.') +param overprovision bool = false + +@description('Optional. When Overprovision is enabled, extensions are launched only on the requested number of VMs which are finally kept. This property will hence ensure that the extensions do not run on the extra overprovisioned VMs.') +param doNotRunExtensionsOnOverprovisionedVMs bool = false + +@description('Optional. Whether to force strictly even Virtual Machine distribution cross x-zones in case there is zone outage.') +param zoneBalance bool = false + +@description('Optional. When true this limits the scale set to a single placement group, of max size 100 virtual machines. NOTE: If singlePlacementGroup is true, it may be modified to false. However, if singlePlacementGroup is false, it may not be modified to true.') +param singlePlacementGroup bool = false + +@description('Optional. Specifies the scale-in policy that decides which virtual machines are chosen for removal when a Virtual Machine Scale Set is scaled-in.') +param scaleInPolicy object = { + rules: [ + 'Default' + ] +} + +@description('Required. The SKU size of the VMs.') +param skuName string + +@description('Optional. The initial instance count of scale set VMs.') +param skuCapacity int = 1 + +@description('Optional. The virtual machine scale set zones. NOTE: Availability zones can only be set when you create the scale set.') +param availabilityZones array = [ 1, 2, 3 ] + +@description('Optional. Tags of the resource.') +param tags object? + +@description('Optional. Enable/Disable usage telemetry for module.') +param enableTelemetry bool = true + +@description('Required. The chosen OS type.') +@allowed([ + 'Windows' + 'Linux' +]) +param osType string + +@description('Generated. Do not provide a value! This date value is used to generate a registration token.') +param baseTime string = utcNow('u') + +@description('Optional. SAS token validity length to use to download files from storage accounts. Usage: \'PT8H\' - valid for 8 hours; \'P5D\' - valid for 5 days; \'P1Y\' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours.') +param sasTokenValidityLength string = 'PT8H' + +@description('Optional. The managed identity definition for this resource.') +param managedIdentities managedIdentitiesType + +var publicKeysFormatted = [for publicKey in publicKeys: { + path: publicKey.path + keyData: publicKey.keyData +}] + +var linuxConfiguration = { + disablePasswordAuthentication: disablePasswordAuthentication + ssh: { + publicKeys: publicKeysFormatted + } + provisionVMAgent: provisionVMAgent +} + +var windowsConfiguration = { + provisionVMAgent: provisionVMAgent + enableAutomaticUpdates: enableAutomaticUpdates + timeZone: empty(timeZone) ? null : timeZone + additionalUnattendContent: empty(additionalUnattendContent) ? null : additionalUnattendContent + winRM: !empty(winRM) ? { + listeners: winRM + } : null +} + +var accountSasProperties = { + signedServices: 'b' + signedPermission: 'r' + signedExpiry: dateTimeAdd(baseTime, sasTokenValidityLength) + signedResourceTypes: 'o' + signedProtocol: 'https' +} + +var 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 enableReferencedModulesTelemetry = false + +var builtInRoleNames = { + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Data Operator for Managed Disks': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '959f8984-c045-4866-89c7-12bf9737be2e') + 'Desktop Virtualization Power On Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '489581de-a3bd-480d-9518-53dea7416b33') + 'Desktop Virtualization Power On Off Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '40c5ff49-9181-41f8-ae61-143b0e78555e') + 'Desktop Virtualization Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a959dbd1-f747-45e3-8ba6-dd80f235f97c') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Disk Backup Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e5e47e6-65f7-47ef-90b5-e5dd4d455f24') + 'Disk Pool Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60fc6e62-5479-42d4-8bf4-67625fcc2840') + 'Disk Restore Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b50d9833-a0cb-478e-945f-707fcc997c13') + 'Disk Snapshot Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce') + 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') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') + 'VM Scanner Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd24ecba3-c1f4-40fa-a7bb-4588a071e8fd') +} + +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.compute-virtualmachinescaleset.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } + } + } + } +} + +resource vmss 'Microsoft.Compute/virtualMachineScaleSets@2022-11-01' = { + name: name + location: location + tags: tags + identity: identity + zones: availabilityZones + properties: { + proximityPlacementGroup: !empty(proximityPlacementGroupResourceId) ? { + id: proximityPlacementGroupResourceId + } : null + upgradePolicy: { + mode: upgradePolicyMode + rollingUpgradePolicy: { + maxBatchInstancePercent: maxBatchInstancePercent + maxUnhealthyInstancePercent: maxUnhealthyInstancePercent + maxUnhealthyUpgradedInstancePercent: maxUnhealthyUpgradedInstancePercent + pauseTimeBetweenBatches: pauseTimeBetweenBatches + } + automaticOSUpgradePolicy: { + enableAutomaticOSUpgrade: enableAutomaticOSUpgrade + disableAutomaticRollback: disableAutomaticRollback + } + } + automaticRepairsPolicy: { + enabled: automaticRepairsPolicyEnabled + gracePeriod: gracePeriod + } + virtualMachineProfile: { + osProfile: { + computerNamePrefix: vmNamePrefix + adminUsername: adminUsername + adminPassword: !empty(adminPassword) ? adminPassword : null + customData: !empty(customData) ? base64(customData) : null + windowsConfiguration: osType == 'Windows' ? windowsConfiguration : null + linuxConfiguration: osType == 'Linux' ? linuxConfiguration : null + secrets: secrets + } + securityProfile: { + encryptionAtHost: encryptionAtHost ? encryptionAtHost : null + securityType: securityType + uefiSettings: securityType == 'TrustedLaunch' ? { + secureBootEnabled: secureBootEnabled + vTpmEnabled: vTpmEnabled + } : null + } + storageProfile: { + imageReference: imageReference + osDisk: { + createOption: osDisk.createOption + diskSizeGB: osDisk.diskSizeGB + caching: contains(osDisk, 'caching') ? osDisk.caching : null + writeAcceleratorEnabled: contains(osDisk, 'writeAcceleratorEnabled') ? osDisk.writeAcceleratorEnabled : null + diffDiskSettings: contains(osDisk, 'diffDiskSettings') ? osDisk.diffDiskSettings : null + osType: contains(osDisk, 'osType') ? osDisk.osType : null + image: contains(osDisk, 'image') ? osDisk.image : null + vhdContainers: contains(osDisk, 'vhdContainers') ? osDisk.vhdContainers : null + managedDisk: { + storageAccountType: osDisk.managedDisk.storageAccountType + diskEncryptionSet: contains(osDisk.managedDisk, 'diskEncryptionSet') ? { + id: osDisk.managedDisk.diskEncryptionSet.id + } : null + } + } + dataDisks: [for (dataDisk, index) in dataDisks: { + lun: index + diskSizeGB: dataDisk.diskSizeGB + createOption: dataDisk.createOption + caching: dataDisk.caching + writeAcceleratorEnabled: contains(osDisk, 'writeAcceleratorEnabled') ? osDisk.writeAcceleratorEnabled : null + managedDisk: { + storageAccountType: dataDisk.managedDisk.storageAccountType + diskEncryptionSet: contains(dataDisk.managedDisk, 'diskEncryptionSet') ? { + id: dataDisk.managedDisk.diskEncryptionSet.id + } : null + } + diskIOPSReadWrite: contains(osDisk, 'diskIOPSReadWrite') ? dataDisk.diskIOPSReadWrite : null + diskMBpsReadWrite: contains(osDisk, 'diskMBpsReadWrite') ? dataDisk.diskMBpsReadWrite : null + }] + } + networkProfile: { + networkInterfaceConfigurations: [for (nicConfiguration, index) in nicConfigurations: { + name: '${name}${nicConfiguration.nicSuffix}configuration-${index}' + properties: { + primary: (index == 0) ? true : any(null) + enableAcceleratedNetworking: contains(nicConfiguration, 'enableAcceleratedNetworking') ? nicConfiguration.enableAcceleratedNetworking : true + networkSecurityGroup: contains(nicConfiguration, 'nsgId') ? { + id: nicConfiguration.nsgId + } : null + ipConfigurations: nicConfiguration.ipConfigurations + } + }] + } + diagnosticsProfile: { + bootDiagnostics: { + enabled: !empty(bootDiagnosticStorageAccountName) + storageUri: !empty(bootDiagnosticStorageAccountName) ? 'https://${bootDiagnosticStorageAccountName}${bootDiagnosticStorageAccountUri}' : null + } + } + licenseType: empty(licenseType) ? null : licenseType + priority: vmPriority + evictionPolicy: enableEvictionPolicy ? 'Deallocate' : null + billingProfile: !empty(vmPriority) && !empty(maxPriceForLowPriorityVm) ? { + maxPrice: maxPriceForLowPriorityVm + } : null + scheduledEventsProfile: scheduledEventsProfile + } + overprovision: overprovision + doNotRunExtensionsOnOverprovisionedVMs: doNotRunExtensionsOnOverprovisionedVMs + zoneBalance: zoneBalance == 'true' ? zoneBalance : null + platformFaultDomainCount: scaleSetFaultDomain + singlePlacementGroup: singlePlacementGroup + additionalCapabilities: { + ultraSSDEnabled: ultraSSDEnabled + } + scaleInPolicy: scaleInPolicy + } + sku: { + name: skuName + capacity: skuCapacity + } + plan: !empty(plan) ? plan : null +} + +module vmss_domainJoinExtension 'extension/main.bicep' = if (extensionDomainJoinConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-DomainJoin' + params: { + virtualMachineScaleSetName: vmss.name + name: 'DomainJoin' + publisher: 'Microsoft.Compute' + type: 'JsonADDomainExtension' + typeHandlerVersion: contains(extensionDomainJoinConfig, 'typeHandlerVersion') ? extensionDomainJoinConfig.typeHandlerVersion : '1.3' + autoUpgradeMinorVersion: contains(extensionDomainJoinConfig, 'autoUpgradeMinorVersion') ? extensionDomainJoinConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDomainJoinConfig, 'enableAutomaticUpgrade') ? extensionDomainJoinConfig.enableAutomaticUpgrade : false + settings: extensionDomainJoinConfig.settings + protectedSettings: { + Password: extensionDomainJoinPassword + } + } +} + +module vmss_microsoftAntiMalwareExtension 'extension/main.bicep' = if (extensionAntiMalwareConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-MicrosoftAntiMalware' + params: { + virtualMachineScaleSetName: vmss.name + name: 'MicrosoftAntiMalware' + publisher: 'Microsoft.Azure.Security' + type: 'IaaSAntimalware' + typeHandlerVersion: contains(extensionAntiMalwareConfig, 'typeHandlerVersion') ? extensionAntiMalwareConfig.typeHandlerVersion : '1.3' + autoUpgradeMinorVersion: contains(extensionAntiMalwareConfig, 'autoUpgradeMinorVersion') ? extensionAntiMalwareConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionAntiMalwareConfig, 'enableAutomaticUpgrade') ? extensionAntiMalwareConfig.enableAutomaticUpgrade : false + settings: extensionAntiMalwareConfig.settings + } + dependsOn: [ + vmss_domainJoinExtension + ] +} + +resource vmss_logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' existing = if (!empty(monitoringWorkspaceId)) { + name: last(split((!empty(monitoringWorkspaceId) ? monitoringWorkspaceId : 'law'), '/'))! + scope: az.resourceGroup(split((!empty(monitoringWorkspaceId) ? monitoringWorkspaceId : '//'), '/')[2], split((!empty(monitoringWorkspaceId) ? monitoringWorkspaceId : '////'), '/')[4]) +} + +module vmss_azureMonitorAgentExtension 'extension/main.bicep' = if (extensionMonitoringAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-AzureMonitorAgent' + params: { + virtualMachineScaleSetName: vmss.name + name: 'AzureMonitorAgent' + publisher: 'Microsoft.Azure.Monitor' + type: osType == 'Windows' ? 'AzureMonitorWindowsAgent' : 'AzureMonitorLinuxAgent' + typeHandlerVersion: contains(extensionMonitoringAgentConfig, 'typeHandlerVersion') ? extensionMonitoringAgentConfig.typeHandlerVersion : (osType == 'Windows' ? '1.22' : '1.29') + autoUpgradeMinorVersion: contains(extensionMonitoringAgentConfig, 'autoUpgradeMinorVersion') ? extensionMonitoringAgentConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionMonitoringAgentConfig, 'enableAutomaticUpgrade') ? extensionMonitoringAgentConfig.enableAutomaticUpgrade : false + settings: { + workspaceId: !empty(monitoringWorkspaceId) ? reference(vmss_logAnalyticsWorkspace.id, vmss_logAnalyticsWorkspace.apiVersion).customerId : '' + GCS_AUTO_CONFIG: osType == 'Linux' ? true : null + } + protectedSettings: { + workspaceKey: !empty(monitoringWorkspaceId) ? vmss_logAnalyticsWorkspace.listKeys().primarySharedKey : '' + } + } + dependsOn: [ + vmss_microsoftAntiMalwareExtension + ] +} + +module vmss_dependencyAgentExtension 'extension/main.bicep' = if (extensionDependencyAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-DependencyAgent' + params: { + virtualMachineScaleSetName: vmss.name + name: 'DependencyAgent' + publisher: 'Microsoft.Azure.Monitoring.DependencyAgent' + type: osType == 'Windows' ? 'DependencyAgentWindows' : 'DependencyAgentLinux' + typeHandlerVersion: contains(extensionDependencyAgentConfig, 'typeHandlerVersion') ? extensionDependencyAgentConfig.typeHandlerVersion : '9.5' + autoUpgradeMinorVersion: contains(extensionDependencyAgentConfig, 'autoUpgradeMinorVersion') ? extensionDependencyAgentConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDependencyAgentConfig, 'enableAutomaticUpgrade') ? extensionDependencyAgentConfig.enableAutomaticUpgrade : true + } + dependsOn: [ + vmss_azureMonitorAgentExtension + ] +} + +module vmss_networkWatcherAgentExtension 'extension/main.bicep' = if (extensionNetworkWatcherAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-NetworkWatcherAgent' + params: { + virtualMachineScaleSetName: vmss.name + name: 'NetworkWatcherAgent' + publisher: 'Microsoft.Azure.NetworkWatcher' + type: osType == 'Windows' ? 'NetworkWatcherAgentWindows' : 'NetworkWatcherAgentLinux' + typeHandlerVersion: contains(extensionNetworkWatcherAgentConfig, 'typeHandlerVersion') ? extensionNetworkWatcherAgentConfig.typeHandlerVersion : '1.4' + autoUpgradeMinorVersion: contains(extensionNetworkWatcherAgentConfig, 'autoUpgradeMinorVersion') ? extensionNetworkWatcherAgentConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionNetworkWatcherAgentConfig, 'enableAutomaticUpgrade') ? extensionNetworkWatcherAgentConfig.enableAutomaticUpgrade : false + } + dependsOn: [ + vmss_dependencyAgentExtension + ] +} + +module vmss_desiredStateConfigurationExtension 'extension/main.bicep' = if (extensionDSCConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-DesiredStateConfiguration' + params: { + virtualMachineScaleSetName: vmss.name + name: 'DesiredStateConfiguration' + publisher: 'Microsoft.Powershell' + type: 'DSC' + typeHandlerVersion: contains(extensionDSCConfig, 'typeHandlerVersion') ? extensionDSCConfig.typeHandlerVersion : '2.77' + autoUpgradeMinorVersion: contains(extensionDSCConfig, 'autoUpgradeMinorVersion') ? extensionDSCConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDSCConfig, 'enableAutomaticUpgrade') ? extensionDSCConfig.enableAutomaticUpgrade : false + settings: contains(extensionDSCConfig, 'settings') ? extensionDSCConfig.settings : {} + protectedSettings: contains(extensionDSCConfig, 'protectedSettings') ? extensionDSCConfig.protectedSettings : {} + } + dependsOn: [ + vmss_networkWatcherAgentExtension + ] +} + +module vmss_customScriptExtension 'extension/main.bicep' = if (extensionCustomScriptConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-CustomScriptExtension' + params: { + virtualMachineScaleSetName: vmss.name + name: 'CustomScriptExtension' + publisher: osType == 'Windows' ? 'Microsoft.Compute' : 'Microsoft.Azure.Extensions' + type: osType == 'Windows' ? 'CustomScriptExtension' : 'CustomScript' + typeHandlerVersion: contains(extensionCustomScriptConfig, 'typeHandlerVersion') ? extensionCustomScriptConfig.typeHandlerVersion : (osType == 'Windows' ? '1.10' : '2.1') + autoUpgradeMinorVersion: contains(extensionCustomScriptConfig, 'autoUpgradeMinorVersion') ? extensionCustomScriptConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionCustomScriptConfig, 'enableAutomaticUpgrade') ? extensionCustomScriptConfig.enableAutomaticUpgrade : false + settings: { + fileUris: [for fileData in extensionCustomScriptConfig.fileData: contains(fileData, 'storageAccountId') ? '${fileData.uri}?${listAccountSas(fileData.storageAccountId, '2019-04-01', accountSasProperties).accountSasToken}' : fileData.uri] + } + protectedSettings: contains(extensionCustomScriptConfig, 'protectedSettings') ? extensionCustomScriptConfig.protectedSettings : {} + } + dependsOn: [ + vmss_desiredStateConfigurationExtension + ] +} + +module vmss_azureDiskEncryptionExtension 'extension/main.bicep' = if (extensionAzureDiskEncryptionConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-AzureDiskEncryption' + params: { + virtualMachineScaleSetName: vmss.name + name: 'AzureDiskEncryption' + publisher: 'Microsoft.Azure.Security' + type: osType == 'Windows' ? 'AzureDiskEncryption' : 'AzureDiskEncryptionForLinux' + typeHandlerVersion: contains(extensionAzureDiskEncryptionConfig, 'typeHandlerVersion') ? extensionAzureDiskEncryptionConfig.typeHandlerVersion : (osType == 'Windows' ? '2.2' : '1.1') + autoUpgradeMinorVersion: contains(extensionAzureDiskEncryptionConfig, 'autoUpgradeMinorVersion') ? extensionAzureDiskEncryptionConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionAzureDiskEncryptionConfig, 'enableAutomaticUpgrade') ? extensionAzureDiskEncryptionConfig.enableAutomaticUpgrade : false + forceUpdateTag: contains(extensionAzureDiskEncryptionConfig, 'forceUpdateTag') ? extensionAzureDiskEncryptionConfig.forceUpdateTag : '1.0' + settings: extensionAzureDiskEncryptionConfig.settings + } + dependsOn: [ + vmss_customScriptExtension + ] +} + +resource vmss_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: vmss +} + +resource vmss_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + }] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: vmss +}] + +resource vmss_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(vmss.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: vmss +}] + +@description('The resource ID of the virtual machine scale set.') +output resourceId string = vmss.id + +@description('The resource group of the virtual machine scale set.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the virtual machine scale set.') +output name string = vmss.name + +@description('The principal ID of the system assigned identity.') +output systemAssignedMIPrincipalId string = vmss.?identity.?principalId ?? '' + +@description('The location the resource was deployed into.') +output location string = vmss.location + +// =============== // +// 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('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 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/compute/virtual-machine-scale-set/main.json b/avm/res/compute/virtual-machine-scale-set/main.json new file mode 100644 index 0000000000..631b4efcc3 --- /dev/null +++ b/avm/res/compute/virtual-machine-scale-set/main.json @@ -0,0 +1,2362 @@ +{ + "$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": "14475705222828543049" + }, + "name": "Virtual Machine Scale Sets", + "description": "This module deploys a Virtual Machine Scale Set.", + "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": { + "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." + } + }, + "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 + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the VMSS." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "encryptionAtHost": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your virtual machine scale sets." + } + }, + "securityType": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Specifies the SecurityType of the virtual machine scale set. It is set as TrustedLaunch to enable UefiSettings." + } + }, + "secureBootEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether secure boot should be enabled on the virtual machine scale set. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings." + } + }, + "vTpmEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether vTPM should be enabled on the virtual machine scale set. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings." + } + }, + "imageReference": { + "type": "object", + "metadata": { + "description": "Required. OS image reference. In case of marketplace images, it's the combination of the publisher, offer, sku, version attributes. In case of custom images it's the resource ID of the custom image." + } + }, + "plan": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Specifies information about the marketplace image used to create the virtual machine. This element is only used for marketplace images. Before you can use a marketplace image from an API, you must enable the image for programmatic use." + } + }, + "osDisk": { + "type": "object", + "metadata": { + "description": "Required. Specifies the OS disk. For security reasons, it is recommended to specify DiskEncryptionSet into the osDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VM Scale sets." + } + }, + "dataDisks": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Specifies the data disks. For security reasons, it is recommended to specify DiskEncryptionSet into the dataDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VM Scale sets." + } + }, + "ultraSSDEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. The flag that enables or disables a capability to have one or more managed data disks with UltraSSD_LRS storage account type on the VM or VMSS. Managed disks with storage account type UltraSSD_LRS can be added to a virtual machine or virtual machine scale set only if this property is enabled." + } + }, + "adminUsername": { + "type": "securestring", + "metadata": { + "description": "Required. Administrator username." + } + }, + "adminPassword": { + "type": "securestring", + "defaultValue": "", + "metadata": { + "description": "Optional. When specifying a Windows Virtual Machine, this value should be passed." + } + }, + "customData": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "scaleSetFaultDomain": { + "type": "int", + "defaultValue": 1, + "metadata": { + "description": "Optional. Fault Domain count for each placement group." + } + }, + "proximityPlacementGroupResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of a proximity placement group." + } + }, + "nicConfigurations": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Required. Configures NICs and PIPs." + } + }, + "vmPriority": { + "type": "string", + "defaultValue": "Regular", + "allowedValues": [ + "Regular", + "Low", + "Spot" + ], + "metadata": { + "description": "Optional. Specifies the priority for the virtual machine." + } + }, + "enableEvictionPolicy": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies the eviction policy for the low priority virtual machine. Will result in 'Deallocate' eviction policy." + } + }, + "maxPriceForLowPriorityVm": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars." + } + }, + "licenseType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "Windows_Client", + "Windows_Server", + "" + ], + "metadata": { + "description": "Optional. Specifies that the image or disk that is being used was licensed on-premises. This element is only used for images that contain the Windows Server operating system." + } + }, + "extensionDomainJoinPassword": { + "type": "securestring", + "defaultValue": "", + "metadata": { + "description": "Optional. Required if name is specified. Password of the user specified in user parameter." + } + }, + "extensionDomainJoinConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Domain Join] extension. Must at least contain the [\"enabled\": true] property to be executed." + } + }, + "extensionAntiMalwareConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Anti Malware] extension. Must at least contain the [\"enabled\": true] property to be executed." + } + }, + "extensionMonitoringAgentConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Monitoring Agent] extension. Must at least contain the [\"enabled\": true] property to be executed." + } + }, + "monitoringWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the monitoring log analytics workspace." + } + }, + "extensionDependencyAgentConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Dependency Agent] extension. Must at least contain the [\"enabled\": true] property to be executed." + } + }, + "extensionNetworkWatcherAgentConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Network Watcher Agent] extension. Must at least contain the [\"enabled\": true] property to be executed." + } + }, + "extensionAzureDiskEncryptionConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Azure Disk Encryption] extension. Must at least contain the [\"enabled\": true] property to be executed. Restrictions: Cannot be enabled on disks that have encryption at host enabled. Managed disks encrypted using Azure Disk Encryption cannot be encrypted using customer-managed keys." + } + }, + "extensionDSCConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Desired State Configuration] extension. Must at least contain the [\"enabled\": true] property to be executed." + } + }, + "extensionCustomScriptConfig": { + "type": "object", + "defaultValue": { + "enabled": false, + "fileData": [] + }, + "metadata": { + "description": "Optional. The configuration for the [Custom Script] extension. Must at least contain the [\"enabled\": true] property to be executed." + } + }, + "bootDiagnosticStorageAccountUri": { + "type": "string", + "defaultValue": "[format('.blob.{0}/', environment().suffixes.storage)]", + "metadata": { + "description": "Optional. Storage account boot diagnostic base URI." + } + }, + "bootDiagnosticStorageAccountName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Storage account used to store boot diagnostic information. Boot diagnostics will be disabled if no value is provided." + } + }, + "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." + } + }, + "upgradePolicyMode": { + "type": "string", + "defaultValue": "Manual", + "allowedValues": [ + "Manual", + "Automatic", + "Rolling" + ], + "metadata": { + "description": "Optional. Specifies the mode of an upgrade to virtual machines in the scale set.' Manual - You control the application of updates to virtual machines in the scale set. You do this by using the manualUpgrade action. ; Automatic - All virtual machines in the scale set are automatically updated at the same time. - Automatic, Manual, Rolling." + } + }, + "maxBatchInstancePercent": { + "type": "int", + "defaultValue": 20, + "metadata": { + "description": "Optional. The maximum percent of total virtual machine instances that will be upgraded simultaneously by the rolling upgrade in one batch. As this is a maximum, unhealthy instances in previous or future batches can cause the percentage of instances in a batch to decrease to ensure higher reliability." + } + }, + "maxUnhealthyInstancePercent": { + "type": "int", + "defaultValue": 20, + "metadata": { + "description": "Optional. The maximum percentage of the total virtual machine instances in the scale set that can be simultaneously unhealthy, either as a result of being upgraded, or by being found in an unhealthy state by the virtual machine health checks before the rolling upgrade aborts. This constraint will be checked prior to starting any batch." + } + }, + "maxUnhealthyUpgradedInstancePercent": { + "type": "int", + "defaultValue": 20, + "metadata": { + "description": "Optional. The maximum percentage of the total virtual machine instances in the scale set that can be simultaneously unhealthy, either as a result of being upgraded, or by being found in an unhealthy state by the virtual machine health checks before the rolling upgrade aborts. This constraint will be checked prior to starting any batch." + } + }, + "pauseTimeBetweenBatches": { + "type": "string", + "defaultValue": "PT0S", + "metadata": { + "description": "Optional. The wait time between completing the update for all virtual machines in one batch and starting the next batch. The time duration should be specified in ISO 8601 format." + } + }, + "enableAutomaticOSUpgrade": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether OS upgrades should automatically be applied to scale set instances in a rolling fashion when a newer version of the OS image becomes available. Default value is false. If this is set to true for Windows based scale sets, enableAutomaticUpdates is automatically set to false and cannot be set to true." + } + }, + "disableAutomaticRollback": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Whether OS image rollback feature should be disabled." + } + }, + "automaticRepairsPolicyEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether automatic repairs should be enabled on the virtual machine scale set." + } + }, + "gracePeriod": { + "type": "string", + "defaultValue": "PT30M", + "metadata": { + "description": "Optional. The amount of time for which automatic repairs are suspended due to a state change on VM. The grace time starts after the state change has completed. This helps avoid premature or accidental repairs. The time duration should be specified in ISO 8601 format. The minimum allowed grace period is 30 minutes (PT30M). The maximum allowed grace period is 90 minutes (PT90M)." + } + }, + "vmNamePrefix": { + "type": "string", + "defaultValue": "vmssvm", + "minLength": 1, + "maxLength": 15, + "metadata": { + "description": "Optional. Specifies the computer name prefix for all of the virtual machines in the scale set." + } + }, + "provisionVMAgent": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Indicates whether virtual machine agent should be provisioned on the virtual machine. When this property is not specified in the request body, default behavior is to set it to true. This will ensure that VM Agent is installed on the VM so that extensions can be added to the VM later." + } + }, + "enableAutomaticUpdates": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning." + } + }, + "timeZone": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Specifies the time zone of the virtual machine. e.g. 'Pacific Standard Time'. Possible values can be `TimeZoneInfo.id` value from time zones returned by `TimeZoneInfo.GetSystemTimeZones`." + } + }, + "additionalUnattendContent": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Specifies additional base-64 encoded XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. - AdditionalUnattendContent object." + } + }, + "winRM": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object." + } + }, + "disablePasswordAuthentication": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether password authentication should be disabled." + } + }, + "publicKeys": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The list of SSH public keys used to authenticate with linux based VMs." + } + }, + "secrets": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Specifies set of certificates that should be installed onto the virtual machines in the scale set." + } + }, + "scheduledEventsProfile": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Specifies Scheduled Event related configurations." + } + }, + "overprovision": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether the Virtual Machine Scale Set should be overprovisioned." + } + }, + "doNotRunExtensionsOnOverprovisionedVMs": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. When Overprovision is enabled, extensions are launched only on the requested number of VMs which are finally kept. This property will hence ensure that the extensions do not run on the extra overprovisioned VMs." + } + }, + "zoneBalance": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Whether to force strictly even Virtual Machine distribution cross x-zones in case there is zone outage." + } + }, + "singlePlacementGroup": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. When true this limits the scale set to a single placement group, of max size 100 virtual machines. NOTE: If singlePlacementGroup is true, it may be modified to false. However, if singlePlacementGroup is false, it may not be modified to true." + } + }, + "scaleInPolicy": { + "type": "object", + "defaultValue": { + "rules": [ + "Default" + ] + }, + "metadata": { + "description": "Optional. Specifies the scale-in policy that decides which virtual machines are chosen for removal when a Virtual Machine Scale Set is scaled-in." + } + }, + "skuName": { + "type": "string", + "metadata": { + "description": "Required. The SKU size of the VMs." + } + }, + "skuCapacity": { + "type": "int", + "defaultValue": 1, + "metadata": { + "description": "Optional. The initial instance count of scale set VMs." + } + }, + "availabilityZones": { + "type": "array", + "defaultValue": [ + 1, + 2, + 3 + ], + "metadata": { + "description": "Optional. The virtual machine scale set zones. NOTE: Availability zones can only be set when you create the scale set." + } + }, + "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." + } + }, + "osType": { + "type": "string", + "allowedValues": [ + "Windows", + "Linux" + ], + "metadata": { + "description": "Required. The chosen OS type." + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('u')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to generate a registration token." + } + }, + "sasTokenValidityLength": { + "type": "string", + "defaultValue": "PT8H", + "metadata": { + "description": "Optional. SAS token validity length to use to download files from storage accounts. Usage: 'PT8H' - valid for 8 hours; 'P5D' - valid for 5 days; 'P1Y' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours." + } + }, + "managedIdentities": { + "$ref": "#/definitions/managedIdentitiesType", + "metadata": { + "description": "Optional. The managed identity definition for this resource." + } + } + }, + "variables": { + "copy": [ + { + "name": "publicKeysFormatted", + "count": "[length(parameters('publicKeys'))]", + "input": { + "path": "[parameters('publicKeys')[copyIndex('publicKeysFormatted')].path]", + "keyData": "[parameters('publicKeys')[copyIndex('publicKeysFormatted')].keyData]" + } + } + ], + "linuxConfiguration": { + "disablePasswordAuthentication": "[parameters('disablePasswordAuthentication')]", + "ssh": { + "publicKeys": "[variables('publicKeysFormatted')]" + }, + "provisionVMAgent": "[parameters('provisionVMAgent')]" + }, + "windowsConfiguration": { + "provisionVMAgent": "[parameters('provisionVMAgent')]", + "enableAutomaticUpdates": "[parameters('enableAutomaticUpdates')]", + "timeZone": "[if(empty(parameters('timeZone')), null(), parameters('timeZone'))]", + "additionalUnattendContent": "[if(empty(parameters('additionalUnattendContent')), null(), parameters('additionalUnattendContent'))]", + "winRM": "[if(not(empty(parameters('winRM'))), createObject('listeners', parameters('winRM')), null())]" + }, + "accountSasProperties": { + "signedServices": "b", + "signedPermission": "r", + "signedExpiry": "[dateTimeAdd(parameters('baseTime'), parameters('sasTokenValidityLength'))]", + "signedResourceTypes": "o", + "signedProtocol": "https" + }, + "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())]", + "enableReferencedModulesTelemetry": false, + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Data Operator for Managed Disks": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '959f8984-c045-4866-89c7-12bf9737be2e')]", + "Desktop Virtualization Power On Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '489581de-a3bd-480d-9518-53dea7416b33')]", + "Desktop Virtualization Power On Off Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '40c5ff49-9181-41f8-ae61-143b0e78555e')]", + "Desktop Virtualization Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a959dbd1-f747-45e3-8ba6-dd80f235f97c')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Disk Backup Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e5e47e6-65f7-47ef-90b5-e5dd4d455f24')]", + "Disk Pool Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60fc6e62-5479-42d4-8bf4-67625fcc2840')]", + "Disk Restore Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b50d9833-a0cb-478e-945f-707fcc997c13')]", + "Disk Snapshot Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce')]", + "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')]", + "Virtual Machine Administrator Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]", + "Virtual Machine User Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')]", + "VM Scanner Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd24ecba3-c1f4-40fa-a7bb-4588a071e8fd')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.compute-virtualmachinescaleset.{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" + } + } + } + } + }, + "vmss": { + "type": "Microsoft.Compute/virtualMachineScaleSets", + "apiVersion": "2022-11-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": "[variables('identity')]", + "zones": "[parameters('availabilityZones')]", + "properties": { + "proximityPlacementGroup": "[if(not(empty(parameters('proximityPlacementGroupResourceId'))), createObject('id', parameters('proximityPlacementGroupResourceId')), null())]", + "upgradePolicy": { + "mode": "[parameters('upgradePolicyMode')]", + "rollingUpgradePolicy": { + "maxBatchInstancePercent": "[parameters('maxBatchInstancePercent')]", + "maxUnhealthyInstancePercent": "[parameters('maxUnhealthyInstancePercent')]", + "maxUnhealthyUpgradedInstancePercent": "[parameters('maxUnhealthyUpgradedInstancePercent')]", + "pauseTimeBetweenBatches": "[parameters('pauseTimeBetweenBatches')]" + }, + "automaticOSUpgradePolicy": { + "enableAutomaticOSUpgrade": "[parameters('enableAutomaticOSUpgrade')]", + "disableAutomaticRollback": "[parameters('disableAutomaticRollback')]" + } + }, + "automaticRepairsPolicy": { + "enabled": "[parameters('automaticRepairsPolicyEnabled')]", + "gracePeriod": "[parameters('gracePeriod')]" + }, + "virtualMachineProfile": { + "osProfile": { + "computerNamePrefix": "[parameters('vmNamePrefix')]", + "adminUsername": "[parameters('adminUsername')]", + "adminPassword": "[if(not(empty(parameters('adminPassword'))), parameters('adminPassword'), null())]", + "customData": "[if(not(empty(parameters('customData'))), base64(parameters('customData')), null())]", + "windowsConfiguration": "[if(equals(parameters('osType'), 'Windows'), variables('windowsConfiguration'), null())]", + "linuxConfiguration": "[if(equals(parameters('osType'), 'Linux'), variables('linuxConfiguration'), null())]", + "secrets": "[parameters('secrets')]" + }, + "securityProfile": { + "encryptionAtHost": "[if(parameters('encryptionAtHost'), parameters('encryptionAtHost'), null())]", + "securityType": "[parameters('securityType')]", + "uefiSettings": "[if(equals(parameters('securityType'), 'TrustedLaunch'), createObject('secureBootEnabled', parameters('secureBootEnabled'), 'vTpmEnabled', parameters('vTpmEnabled')), null())]" + }, + "storageProfile": { + "copy": [ + { + "name": "dataDisks", + "count": "[length(parameters('dataDisks'))]", + "input": { + "lun": "[copyIndex('dataDisks')]", + "diskSizeGB": "[parameters('dataDisks')[copyIndex('dataDisks')].diskSizeGB]", + "createOption": "[parameters('dataDisks')[copyIndex('dataDisks')].createOption]", + "caching": "[parameters('dataDisks')[copyIndex('dataDisks')].caching]", + "writeAcceleratorEnabled": "[if(contains(parameters('osDisk'), 'writeAcceleratorEnabled'), parameters('osDisk').writeAcceleratorEnabled, null())]", + "managedDisk": { + "storageAccountType": "[parameters('dataDisks')[copyIndex('dataDisks')].managedDisk.storageAccountType]", + "diskEncryptionSet": "[if(contains(parameters('dataDisks')[copyIndex('dataDisks')].managedDisk, 'diskEncryptionSet'), createObject('id', parameters('dataDisks')[copyIndex('dataDisks')].managedDisk.diskEncryptionSet.id), null())]" + }, + "diskIOPSReadWrite": "[if(contains(parameters('osDisk'), 'diskIOPSReadWrite'), parameters('dataDisks')[copyIndex('dataDisks')].diskIOPSReadWrite, null())]", + "diskMBpsReadWrite": "[if(contains(parameters('osDisk'), 'diskMBpsReadWrite'), parameters('dataDisks')[copyIndex('dataDisks')].diskMBpsReadWrite, null())]" + } + } + ], + "imageReference": "[parameters('imageReference')]", + "osDisk": { + "createOption": "[parameters('osDisk').createOption]", + "diskSizeGB": "[parameters('osDisk').diskSizeGB]", + "caching": "[if(contains(parameters('osDisk'), 'caching'), parameters('osDisk').caching, null())]", + "writeAcceleratorEnabled": "[if(contains(parameters('osDisk'), 'writeAcceleratorEnabled'), parameters('osDisk').writeAcceleratorEnabled, null())]", + "diffDiskSettings": "[if(contains(parameters('osDisk'), 'diffDiskSettings'), parameters('osDisk').diffDiskSettings, null())]", + "osType": "[if(contains(parameters('osDisk'), 'osType'), parameters('osDisk').osType, null())]", + "image": "[if(contains(parameters('osDisk'), 'image'), parameters('osDisk').image, null())]", + "vhdContainers": "[if(contains(parameters('osDisk'), 'vhdContainers'), parameters('osDisk').vhdContainers, null())]", + "managedDisk": { + "storageAccountType": "[parameters('osDisk').managedDisk.storageAccountType]", + "diskEncryptionSet": "[if(contains(parameters('osDisk').managedDisk, 'diskEncryptionSet'), createObject('id', parameters('osDisk').managedDisk.diskEncryptionSet.id), null())]" + } + } + }, + "networkProfile": { + "copy": [ + { + "name": "networkInterfaceConfigurations", + "count": "[length(parameters('nicConfigurations'))]", + "input": { + "name": "[format('{0}{1}configuration-{2}', parameters('name'), parameters('nicConfigurations')[copyIndex('networkInterfaceConfigurations')].nicSuffix, copyIndex('networkInterfaceConfigurations'))]", + "properties": { + "primary": "[if(equals(copyIndex('networkInterfaceConfigurations'), 0), true(), null())]", + "enableAcceleratedNetworking": "[if(contains(parameters('nicConfigurations')[copyIndex('networkInterfaceConfigurations')], 'enableAcceleratedNetworking'), parameters('nicConfigurations')[copyIndex('networkInterfaceConfigurations')].enableAcceleratedNetworking, true())]", + "networkSecurityGroup": "[if(contains(parameters('nicConfigurations')[copyIndex('networkInterfaceConfigurations')], 'nsgId'), createObject('id', parameters('nicConfigurations')[copyIndex('networkInterfaceConfigurations')].nsgId), null())]", + "ipConfigurations": "[parameters('nicConfigurations')[copyIndex('networkInterfaceConfigurations')].ipConfigurations]" + } + } + } + ] + }, + "diagnosticsProfile": { + "bootDiagnostics": { + "enabled": "[not(empty(parameters('bootDiagnosticStorageAccountName')))]", + "storageUri": "[if(not(empty(parameters('bootDiagnosticStorageAccountName'))), format('https://{0}{1}', parameters('bootDiagnosticStorageAccountName'), parameters('bootDiagnosticStorageAccountUri')), null())]" + } + }, + "licenseType": "[if(empty(parameters('licenseType')), null(), parameters('licenseType'))]", + "priority": "[parameters('vmPriority')]", + "evictionPolicy": "[if(parameters('enableEvictionPolicy'), 'Deallocate', null())]", + "billingProfile": "[if(and(not(empty(parameters('vmPriority'))), not(empty(parameters('maxPriceForLowPriorityVm')))), createObject('maxPrice', parameters('maxPriceForLowPriorityVm')), null())]", + "scheduledEventsProfile": "[parameters('scheduledEventsProfile')]" + }, + "overprovision": "[parameters('overprovision')]", + "doNotRunExtensionsOnOverprovisionedVMs": "[parameters('doNotRunExtensionsOnOverprovisionedVMs')]", + "zoneBalance": "[if(equals(parameters('zoneBalance'), 'true'), parameters('zoneBalance'), null())]", + "platformFaultDomainCount": "[parameters('scaleSetFaultDomain')]", + "singlePlacementGroup": "[parameters('singlePlacementGroup')]", + "additionalCapabilities": { + "ultraSSDEnabled": "[parameters('ultraSSDEnabled')]" + }, + "scaleInPolicy": "[parameters('scaleInPolicy')]" + }, + "sku": { + "name": "[parameters('skuName')]", + "capacity": "[parameters('skuCapacity')]" + }, + "plan": "[if(not(empty(parameters('plan'))), parameters('plan'), null())]" + }, + "vmss_logAnalyticsWorkspace": { + "condition": "[not(empty(parameters('monitoringWorkspaceId')))]", + "existing": true, + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2021-06-01", + "subscriptionId": "[split(if(not(empty(parameters('monitoringWorkspaceId'))), parameters('monitoringWorkspaceId'), '//'), '/')[2]]", + "resourceGroup": "[split(if(not(empty(parameters('monitoringWorkspaceId'))), parameters('monitoringWorkspaceId'), '////'), '/')[4]]", + "name": "[last(split(if(not(empty(parameters('monitoringWorkspaceId'))), parameters('monitoringWorkspaceId'), 'law'), '/'))]" + }, + "vmss_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.Compute/virtualMachineScaleSets/{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": [ + "vmss" + ] + }, + "vmss_diagnosticSettings": { + "copy": { + "name": "vmss_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Compute/virtualMachineScaleSets/{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 + } + } + ], + "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": [ + "vmss" + ] + }, + "vmss_roleAssignments": { + "copy": { + "name": "vmss_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Compute/virtualMachineScaleSets/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Compute/virtualMachineScaleSets', 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": [ + "vmss" + ] + }, + "vmss_domainJoinExtension": { + "condition": "[parameters('extensionDomainJoinConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-VMSS-DomainJoin', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineScaleSetName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "DomainJoin" + }, + "publisher": { + "value": "Microsoft.Compute" + }, + "type": { + "value": "JsonADDomainExtension" + }, + "typeHandlerVersion": "[if(contains(parameters('extensionDomainJoinConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionDomainJoinConfig').typeHandlerVersion), createObject('value', '1.3'))]", + "autoUpgradeMinorVersion": "[if(contains(parameters('extensionDomainJoinConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionDomainJoinConfig').autoUpgradeMinorVersion), createObject('value', true()))]", + "enableAutomaticUpgrade": "[if(contains(parameters('extensionDomainJoinConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionDomainJoinConfig').enableAutomaticUpgrade), createObject('value', false()))]", + "settings": { + "value": "[parameters('extensionDomainJoinConfig').settings]" + }, + "protectedSettings": { + "value": { + "Password": "[parameters('extensionDomainJoinPassword')]" + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "3680417048986934448" + }, + "name": "Virtual Machine Scale Set Extensions", + "description": "This module deploys a Virtual Machine Scale Set Extension.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "virtualMachineScaleSetName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent virtual machine scale set that extension is provisioned for. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine scale set extension." + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher." + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler." + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings." + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings." + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." + } + } + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachineScaleSets/extensions", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('virtualMachineScaleSetName'), parameters('name'))]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the extension." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The ResourceId of the extension." + }, + "value": "[resourceId('Microsoft.Compute/virtualMachineScaleSets/extensions', parameters('virtualMachineScaleSetName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "vmss" + ] + }, + "vmss_microsoftAntiMalwareExtension": { + "condition": "[parameters('extensionAntiMalwareConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-VMSS-MicrosoftAntiMalware', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineScaleSetName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "MicrosoftAntiMalware" + }, + "publisher": { + "value": "Microsoft.Azure.Security" + }, + "type": { + "value": "IaaSAntimalware" + }, + "typeHandlerVersion": "[if(contains(parameters('extensionAntiMalwareConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionAntiMalwareConfig').typeHandlerVersion), createObject('value', '1.3'))]", + "autoUpgradeMinorVersion": "[if(contains(parameters('extensionAntiMalwareConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionAntiMalwareConfig').autoUpgradeMinorVersion), createObject('value', true()))]", + "enableAutomaticUpgrade": "[if(contains(parameters('extensionAntiMalwareConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionAntiMalwareConfig').enableAutomaticUpgrade), createObject('value', false()))]", + "settings": { + "value": "[parameters('extensionAntiMalwareConfig').settings]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "3680417048986934448" + }, + "name": "Virtual Machine Scale Set Extensions", + "description": "This module deploys a Virtual Machine Scale Set Extension.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "virtualMachineScaleSetName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent virtual machine scale set that extension is provisioned for. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine scale set extension." + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher." + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler." + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings." + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings." + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." + } + } + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachineScaleSets/extensions", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('virtualMachineScaleSetName'), parameters('name'))]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the extension." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The ResourceId of the extension." + }, + "value": "[resourceId('Microsoft.Compute/virtualMachineScaleSets/extensions', parameters('virtualMachineScaleSetName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "vmss", + "vmss_domainJoinExtension" + ] + }, + "vmss_azureMonitorAgentExtension": { + "condition": "[parameters('extensionMonitoringAgentConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-VMSS-AzureMonitorAgent', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineScaleSetName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "AzureMonitorAgent" + }, + "publisher": { + "value": "Microsoft.Azure.Monitor" + }, + "type": "[if(equals(parameters('osType'), 'Windows'), createObject('value', 'AzureMonitorWindowsAgent'), createObject('value', 'AzureMonitorLinuxAgent'))]", + "typeHandlerVersion": "[if(contains(parameters('extensionMonitoringAgentConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionMonitoringAgentConfig').typeHandlerVersion), if(equals(parameters('osType'), 'Windows'), createObject('value', '1.22'), createObject('value', '1.29')))]", + "autoUpgradeMinorVersion": "[if(contains(parameters('extensionMonitoringAgentConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionMonitoringAgentConfig').autoUpgradeMinorVersion), createObject('value', true()))]", + "enableAutomaticUpgrade": "[if(contains(parameters('extensionMonitoringAgentConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionMonitoringAgentConfig').enableAutomaticUpgrade), createObject('value', false()))]", + "settings": { + "value": { + "workspaceId": "[if(not(empty(parameters('monitoringWorkspaceId'))), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(if(not(empty(parameters('monitoringWorkspaceId'))), parameters('monitoringWorkspaceId'), '//'), '/')[2], split(if(not(empty(parameters('monitoringWorkspaceId'))), parameters('monitoringWorkspaceId'), '////'), '/')[4]), 'Microsoft.OperationalInsights/workspaces', last(split(if(not(empty(parameters('monitoringWorkspaceId'))), parameters('monitoringWorkspaceId'), 'law'), '/'))), '2021-06-01').customerId, '')]", + "GCS_AUTO_CONFIG": "[if(equals(parameters('osType'), 'Linux'), true(), null())]" + } + }, + "protectedSettings": { + "value": { + "workspaceKey": "[if(not(empty(parameters('monitoringWorkspaceId'))), listKeys(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(if(not(empty(parameters('monitoringWorkspaceId'))), parameters('monitoringWorkspaceId'), '//'), '/')[2], split(if(not(empty(parameters('monitoringWorkspaceId'))), parameters('monitoringWorkspaceId'), '////'), '/')[4]), 'Microsoft.OperationalInsights/workspaces', last(split(if(not(empty(parameters('monitoringWorkspaceId'))), parameters('monitoringWorkspaceId'), 'law'), '/'))), '2021-06-01').primarySharedKey, '')]" + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "3680417048986934448" + }, + "name": "Virtual Machine Scale Set Extensions", + "description": "This module deploys a Virtual Machine Scale Set Extension.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "virtualMachineScaleSetName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent virtual machine scale set that extension is provisioned for. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine scale set extension." + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher." + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler." + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings." + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings." + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." + } + } + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachineScaleSets/extensions", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('virtualMachineScaleSetName'), parameters('name'))]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the extension." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The ResourceId of the extension." + }, + "value": "[resourceId('Microsoft.Compute/virtualMachineScaleSets/extensions', parameters('virtualMachineScaleSetName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "vmss", + "vmss_logAnalyticsWorkspace", + "vmss_microsoftAntiMalwareExtension" + ] + }, + "vmss_dependencyAgentExtension": { + "condition": "[parameters('extensionDependencyAgentConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-VMSS-DependencyAgent', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineScaleSetName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "DependencyAgent" + }, + "publisher": { + "value": "Microsoft.Azure.Monitoring.DependencyAgent" + }, + "type": "[if(equals(parameters('osType'), 'Windows'), createObject('value', 'DependencyAgentWindows'), createObject('value', 'DependencyAgentLinux'))]", + "typeHandlerVersion": "[if(contains(parameters('extensionDependencyAgentConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionDependencyAgentConfig').typeHandlerVersion), createObject('value', '9.5'))]", + "autoUpgradeMinorVersion": "[if(contains(parameters('extensionDependencyAgentConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionDependencyAgentConfig').autoUpgradeMinorVersion), createObject('value', true()))]", + "enableAutomaticUpgrade": "[if(contains(parameters('extensionDependencyAgentConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionDependencyAgentConfig').enableAutomaticUpgrade), createObject('value', true()))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "3680417048986934448" + }, + "name": "Virtual Machine Scale Set Extensions", + "description": "This module deploys a Virtual Machine Scale Set Extension.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "virtualMachineScaleSetName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent virtual machine scale set that extension is provisioned for. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine scale set extension." + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher." + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler." + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings." + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings." + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." + } + } + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachineScaleSets/extensions", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('virtualMachineScaleSetName'), parameters('name'))]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the extension." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The ResourceId of the extension." + }, + "value": "[resourceId('Microsoft.Compute/virtualMachineScaleSets/extensions', parameters('virtualMachineScaleSetName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "vmss", + "vmss_azureMonitorAgentExtension" + ] + }, + "vmss_networkWatcherAgentExtension": { + "condition": "[parameters('extensionNetworkWatcherAgentConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-VMSS-NetworkWatcherAgent', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineScaleSetName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "NetworkWatcherAgent" + }, + "publisher": { + "value": "Microsoft.Azure.NetworkWatcher" + }, + "type": "[if(equals(parameters('osType'), 'Windows'), createObject('value', 'NetworkWatcherAgentWindows'), createObject('value', 'NetworkWatcherAgentLinux'))]", + "typeHandlerVersion": "[if(contains(parameters('extensionNetworkWatcherAgentConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionNetworkWatcherAgentConfig').typeHandlerVersion), createObject('value', '1.4'))]", + "autoUpgradeMinorVersion": "[if(contains(parameters('extensionNetworkWatcherAgentConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionNetworkWatcherAgentConfig').autoUpgradeMinorVersion), createObject('value', true()))]", + "enableAutomaticUpgrade": "[if(contains(parameters('extensionNetworkWatcherAgentConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionNetworkWatcherAgentConfig').enableAutomaticUpgrade), createObject('value', false()))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "3680417048986934448" + }, + "name": "Virtual Machine Scale Set Extensions", + "description": "This module deploys a Virtual Machine Scale Set Extension.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "virtualMachineScaleSetName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent virtual machine scale set that extension is provisioned for. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine scale set extension." + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher." + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler." + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings." + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings." + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." + } + } + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachineScaleSets/extensions", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('virtualMachineScaleSetName'), parameters('name'))]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the extension." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The ResourceId of the extension." + }, + "value": "[resourceId('Microsoft.Compute/virtualMachineScaleSets/extensions', parameters('virtualMachineScaleSetName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "vmss", + "vmss_dependencyAgentExtension" + ] + }, + "vmss_desiredStateConfigurationExtension": { + "condition": "[parameters('extensionDSCConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-VMSS-DesiredStateConfiguration', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineScaleSetName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "DesiredStateConfiguration" + }, + "publisher": { + "value": "Microsoft.Powershell" + }, + "type": { + "value": "DSC" + }, + "typeHandlerVersion": "[if(contains(parameters('extensionDSCConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionDSCConfig').typeHandlerVersion), createObject('value', '2.77'))]", + "autoUpgradeMinorVersion": "[if(contains(parameters('extensionDSCConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionDSCConfig').autoUpgradeMinorVersion), createObject('value', true()))]", + "enableAutomaticUpgrade": "[if(contains(parameters('extensionDSCConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionDSCConfig').enableAutomaticUpgrade), createObject('value', false()))]", + "settings": "[if(contains(parameters('extensionDSCConfig'), 'settings'), createObject('value', parameters('extensionDSCConfig').settings), createObject('value', createObject()))]", + "protectedSettings": "[if(contains(parameters('extensionDSCConfig'), 'protectedSettings'), createObject('value', parameters('extensionDSCConfig').protectedSettings), createObject('value', createObject()))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "3680417048986934448" + }, + "name": "Virtual Machine Scale Set Extensions", + "description": "This module deploys a Virtual Machine Scale Set Extension.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "virtualMachineScaleSetName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent virtual machine scale set that extension is provisioned for. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine scale set extension." + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher." + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler." + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings." + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings." + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." + } + } + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachineScaleSets/extensions", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('virtualMachineScaleSetName'), parameters('name'))]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the extension." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The ResourceId of the extension." + }, + "value": "[resourceId('Microsoft.Compute/virtualMachineScaleSets/extensions', parameters('virtualMachineScaleSetName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "vmss", + "vmss_networkWatcherAgentExtension" + ] + }, + "vmss_customScriptExtension": { + "condition": "[parameters('extensionCustomScriptConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-VMSS-CustomScriptExtension', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineScaleSetName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "CustomScriptExtension" + }, + "publisher": "[if(equals(parameters('osType'), 'Windows'), createObject('value', 'Microsoft.Compute'), createObject('value', 'Microsoft.Azure.Extensions'))]", + "type": "[if(equals(parameters('osType'), 'Windows'), createObject('value', 'CustomScriptExtension'), createObject('value', 'CustomScript'))]", + "typeHandlerVersion": "[if(contains(parameters('extensionCustomScriptConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionCustomScriptConfig').typeHandlerVersion), if(equals(parameters('osType'), 'Windows'), createObject('value', '1.10'), createObject('value', '2.1')))]", + "autoUpgradeMinorVersion": "[if(contains(parameters('extensionCustomScriptConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionCustomScriptConfig').autoUpgradeMinorVersion), createObject('value', true()))]", + "enableAutomaticUpgrade": "[if(contains(parameters('extensionCustomScriptConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionCustomScriptConfig').enableAutomaticUpgrade), createObject('value', false()))]", + "settings": { + "value": { + "copy": [ + { + "name": "fileUris", + "count": "[length(parameters('extensionCustomScriptConfig').fileData)]", + "input": "[if(contains(parameters('extensionCustomScriptConfig').fileData[copyIndex('fileUris')], 'storageAccountId'), format('{0}?{1}', parameters('extensionCustomScriptConfig').fileData[copyIndex('fileUris')].uri, listAccountSas(parameters('extensionCustomScriptConfig').fileData[copyIndex('fileUris')].storageAccountId, '2019-04-01', variables('accountSasProperties')).accountSasToken), parameters('extensionCustomScriptConfig').fileData[copyIndex('fileUris')].uri)]" + } + ] + } + }, + "protectedSettings": "[if(contains(parameters('extensionCustomScriptConfig'), 'protectedSettings'), createObject('value', parameters('extensionCustomScriptConfig').protectedSettings), createObject('value', createObject()))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "3680417048986934448" + }, + "name": "Virtual Machine Scale Set Extensions", + "description": "This module deploys a Virtual Machine Scale Set Extension.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "virtualMachineScaleSetName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent virtual machine scale set that extension is provisioned for. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine scale set extension." + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher." + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler." + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings." + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings." + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." + } + } + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachineScaleSets/extensions", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('virtualMachineScaleSetName'), parameters('name'))]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the extension." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The ResourceId of the extension." + }, + "value": "[resourceId('Microsoft.Compute/virtualMachineScaleSets/extensions', parameters('virtualMachineScaleSetName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "vmss", + "vmss_desiredStateConfigurationExtension" + ] + }, + "vmss_azureDiskEncryptionExtension": { + "condition": "[parameters('extensionAzureDiskEncryptionConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-VMSS-AzureDiskEncryption', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineScaleSetName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "AzureDiskEncryption" + }, + "publisher": { + "value": "Microsoft.Azure.Security" + }, + "type": "[if(equals(parameters('osType'), 'Windows'), createObject('value', 'AzureDiskEncryption'), createObject('value', 'AzureDiskEncryptionForLinux'))]", + "typeHandlerVersion": "[if(contains(parameters('extensionAzureDiskEncryptionConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionAzureDiskEncryptionConfig').typeHandlerVersion), if(equals(parameters('osType'), 'Windows'), createObject('value', '2.2'), createObject('value', '1.1')))]", + "autoUpgradeMinorVersion": "[if(contains(parameters('extensionAzureDiskEncryptionConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionAzureDiskEncryptionConfig').autoUpgradeMinorVersion), createObject('value', true()))]", + "enableAutomaticUpgrade": "[if(contains(parameters('extensionAzureDiskEncryptionConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionAzureDiskEncryptionConfig').enableAutomaticUpgrade), createObject('value', false()))]", + "forceUpdateTag": "[if(contains(parameters('extensionAzureDiskEncryptionConfig'), 'forceUpdateTag'), createObject('value', parameters('extensionAzureDiskEncryptionConfig').forceUpdateTag), createObject('value', '1.0'))]", + "settings": { + "value": "[parameters('extensionAzureDiskEncryptionConfig').settings]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "3680417048986934448" + }, + "name": "Virtual Machine Scale Set Extensions", + "description": "This module deploys a Virtual Machine Scale Set Extension.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "virtualMachineScaleSetName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent virtual machine scale set that extension is provisioned for. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine scale set extension." + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher." + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler." + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings." + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings." + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." + } + } + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachineScaleSets/extensions", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('virtualMachineScaleSetName'), parameters('name'))]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the extension." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The ResourceId of the extension." + }, + "value": "[resourceId('Microsoft.Compute/virtualMachineScaleSets/extensions', parameters('virtualMachineScaleSetName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "vmss", + "vmss_customScriptExtension" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the virtual machine scale set." + }, + "value": "[resourceId('Microsoft.Compute/virtualMachineScaleSets', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the virtual machine scale set." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the virtual machine scale set." + }, + "value": "[parameters('name')]" + }, + "systemAssignedMIPrincipalId": { + "type": "string", + "metadata": { + "description": "The principal ID of the system assigned identity." + }, + "value": "[coalesce(tryGet(tryGet(reference('vmss', '2022-11-01', 'full'), 'identity'), 'principalId'), '')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('vmss', '2022-11-01', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.defaults/dependencies.bicep b/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.defaults/dependencies.bicep new file mode 100644 index 0000000000..9edda99f16 --- /dev/null +++ b/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.defaults/dependencies.bicep @@ -0,0 +1,86 @@ +@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 + +@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 SSH Key generation.') +param sshDeploymentScriptName string + +@description('Required. The name of the SSH Key to create.') +param sshKeyName string + +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) + } + } + ] + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource msiRGContrRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(resourceGroup().id, 'Contributor', managedIdentity.id) + scope: resourceGroup() + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + principalType: 'ServicePrincipal' + } +} + +resource sshDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: sshDeploymentScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + azPowerShellVersion: '9.0' + retentionInterval: 'P1D' + arguments: '-SSHKeyName "${sshKeyName}" -ResourceGroupName "${resourceGroup().name}"' + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/New-SSHKey.ps1') + } + dependsOn: [ + msiRGContrRoleAssignment + ] +} + +resource sshKey 'Microsoft.Compute/sshPublicKeys@2022-03-01' = { + name: sshKeyName + location: location + properties: { + publicKey: sshDeploymentScript.properties.outputs.publicKey + } +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The Public Key of the created SSH Key.') +output SSHKeyPublicKey string = sshKey.properties.publicKey diff --git a/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.defaults/main.test.bicep b/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.defaults/main.test.bicep new file mode 100644 index 0000000000..e775db83ba --- /dev/null +++ b/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.defaults/main.test.bicep @@ -0,0 +1,96 @@ +targetScope = 'subscription' + +metadata name = 'Using only defaults for Linux' +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}-compute.virtualmachinescalesets-${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 = 'cvmsslinmin' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + location: resourceLocation + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + sshDeploymentScriptName: 'dep-${namePrefix}-ds-${serviceShort}' + sshKeyName: 'dep-${namePrefix}-ssh-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + adminUsername: 'scaleSetAdmin' + imageReference: { + publisher: 'Canonical' + offer: '0001-com-ubuntu-server-jammy' + sku: '22_04-lts-gen2' + version: 'latest' + } + osDisk: { + createOption: 'fromImage' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Linux' + skuName: 'Standard_B12ms' + disablePasswordAuthentication: true + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig1' + properties: { + subnet: { + id: nestedDependencies.outputs.subnetResourceId + } + } + } + ] + nicSuffix: '-nic01' + } + ] + publicKeys: [ + { + keyData: nestedDependencies.outputs.SSHKeyPublicKey + path: '/home/scaleSetAdmin/.ssh/authorized_keys' + } + ] + } +}] diff --git a/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.max/dependencies.bicep b/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.max/dependencies.bicep new file mode 100644 index 0000000000..cb6cff2726 --- /dev/null +++ b/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.max/dependencies.bicep @@ -0,0 +1,193 @@ +@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 + +@description('Required. The name of the Key Vault to create.') +param keyVaultName string + +@description('Required. The name of the Storage Account to create.') +param storageAccountName string + +@description('Required. The name of the Deployment Script used to upload data to the Storage Account.') +param storageUploadDeploymentScriptName 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 SSH Key generation.') +param sshDeploymentScriptName string + +@description('Required. The name of the SSH Key to create.') +param sshKeyName string + +var storageAccountCSEFileName = 'scriptExtensionMasterInstaller.ps1' +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) + } + } + ] + } +} + +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 key 'keys@2022-07-01' = { + name: 'encryptionKey' + properties: { + kty: 'RSA' + } + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource msiRGContrRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(resourceGroup().id, 'Contributor', managedIdentity.id) + scope: resourceGroup() + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + principalType: 'ServicePrincipal' + } +} + +resource msiKVCryptoUserRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(keyVault::key.id, 'Key Vault Crypto User', managedIdentity.id) + scope: keyVault::key + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User + principalType: 'ServicePrincipal' + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-09-01' = { + name: storageAccountName + location: location + sku: { + name: 'Standard_LRS' + } + kind: 'StorageV2' + + resource blobService 'blobServices@2021-09-01' = { + name: 'default' + + resource container 'containers@2021-09-01' = { + name: 'scripts' + } + } +} + +resource storageUpload 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: storageUploadDeploymentScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + azPowerShellVersion: '9.0' + retentionInterval: 'P1D' + arguments: '-StorageAccountName "${storageAccount.name}" -ResourceGroupName "${resourceGroup().name}" -ContainerName "${storageAccount::blobService::container.name}" -FileName "${storageAccountCSEFileName}"' + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/Set-BlobContent.ps1') + } + dependsOn: [ + msiRGContrRoleAssignment + ] +} + +resource sshDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: sshDeploymentScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + azPowerShellVersion: '9.0' + retentionInterval: 'P1D' + arguments: '-SSHKeyName "${sshKeyName}" -ResourceGroupName "${resourceGroup().name}"' + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/New-SSHKey.ps1') + } + dependsOn: [ + msiRGContrRoleAssignment + ] +} + +resource sshKey 'Microsoft.Compute/sshPublicKeys@2022-03-01' = { + name: sshKeyName + location: location + properties: { + publicKey: sshDeploymentScript.properties.outputs.publicKey + } +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].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 + +@description('The resource ID of the created Key Vault.') +output keyVaultResourceId string = keyVault.id + +@description('The URL of the created Key Vault.') +output keyVaultUrl string = keyVault.properties.vaultUri + +@description('The URL of the created Key Vault Encryption Key.') +output keyVaultEncryptionKeyUrl string = keyVault::key.properties.keyUriWithVersion + +@description('The name of the created Storage Account.') +output storageAccountName string = storageAccount.name + +@description('The resource ID of the created Storage Account.') +output storageAccountResourceId string = storageAccount.id + +@description('The URL of the Custom Script Extension in the created Storage Account') +output storageAccountCSEFileUrl string = '${storageAccount.properties.primaryEndpoints.blob}${storageAccount::blobService::container.name}/${storageAccountCSEFileName}' + +@description('The Public Key of the created SSH Key.') +output SSHKeyPublicKey string = sshKey.properties.publicKey diff --git a/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.max/main.test.bicep b/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.max/main.test.bicep new file mode 100644 index 0000000000..80b7f9e661 --- /dev/null +++ b/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.max/main.test.bicep @@ -0,0 +1,211 @@ +targetScope = 'subscription' + +metadata name = 'Using large parameter set for Linux' +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}-compute.virtualmachinescalesets-${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 = 'cvmsslinmax' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + location: resourceLocation + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}' + storageAccountName: take('dep${namePrefix}sa${serviceShort}01', 24) + storageUploadDeploymentScriptName: 'dep-${namePrefix}-sads-${serviceShort}' + sshDeploymentScriptName: 'dep-${namePrefix}-ds-${serviceShort}' + sshKeyName: 'dep-${namePrefix}-ssh-${serviceShort}' + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-diagnosticDependencies' + params: { + storageAccountName: take('dep${namePrefix}diasa${serviceShort}01', 24) + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}' + eventHubNamespaceName: 'dep-${namePrefix}-evhns-${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: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + adminUsername: 'scaleSetAdmin' + imageReference: { + publisher: 'Canonical' + offer: '0001-com-ubuntu-server-jammy' + sku: '22_04-lts-gen2' + version: 'latest' + } + osDisk: { + createOption: 'fromImage' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Linux' + skuName: 'Standard_B12ms' + availabilityZones: [ + '2' + ] + bootDiagnosticStorageAccountName: nestedDependencies.outputs.storageAccountName + dataDisks: [ + { + caching: 'ReadOnly' + createOption: 'Empty' + diskSizeGB: '256' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + { + caching: 'ReadOnly' + createOption: 'Empty' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + ] + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + disablePasswordAuthentication: true + encryptionAtHost: false + extensionCustomScriptConfig: { + enabled: true + fileData: [ + { + storageAccountId: nestedDependencies.outputs.storageAccountResourceId + uri: nestedDependencies.outputs.storageAccountCSEFileUrl + } + ] + protectedSettings: { + commandToExecute: 'sudo apt-get update' + } + } + extensionDependencyAgentConfig: { + enabled: true + } + extensionAzureDiskEncryptionConfig: { + enabled: true + settings: { + EncryptionOperation: 'EnableEncryption' + KekVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + KeyEncryptionAlgorithm: 'RSA-OAEP' + KeyEncryptionKeyURL: nestedDependencies.outputs.keyVaultEncryptionKeyUrl + KeyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + KeyVaultURL: nestedDependencies.outputs.keyVaultUrl + ResizeOSDisk: 'false' + VolumeType: 'All' + } + } + extensionMonitoringAgentConfig: { + enabled: true + } + extensionNetworkWatcherAgentConfig: { + enabled: true + } + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig1' + properties: { + subnet: { + id: nestedDependencies.outputs.subnetResourceId + } + } + } + ] + nicSuffix: '-nic01' + } + ] + publicKeys: [ + { + keyData: nestedDependencies.outputs.SSHKeyPublicKey + path: '/home/scaleSetAdmin/.ssh/authorized_keys' + } + ] + roleAssignments: [ + { + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + roleDefinitionIdOrName: 'Reader' + principalType: 'ServicePrincipal' + } + ] + scaleSetFaultDomain: 1 + skuCapacity: 1 + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + upgradePolicyMode: 'Manual' + vmNamePrefix: 'vmsslinvm' + vmPriority: 'Regular' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.ssecmk/dependencies.bicep b/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.ssecmk/dependencies.bicep new file mode 100644 index 0000000000..c6780826ea --- /dev/null +++ b/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.ssecmk/dependencies.bicep @@ -0,0 +1,148 @@ +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Key Vault to create.') +param keyVaultName string + +@description('Required. The name of the Disk Encryption Set to create.') +param diskEncryptionSetName 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 SSH Key generation.') +param sshDeploymentScriptName string + +@description('Required. The name of the SSH Key to create.') +param sshKeyName string + +@description('Optional. The location to deploy resources 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) + } + } + ] + } +} + +resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' + } + tenantId: tenant().tenantId + enablePurgeProtection: true // Required by disk encryption set + softDeleteRetentionInDays: 7 + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } + + resource key 'keys@2022-07-01' = { + name: 'keyEncryptionKey' + properties: { + kty: 'RSA' + } + } +} + +resource diskEncryptionSet 'Microsoft.Compute/diskEncryptionSets@2021-04-01' = { + name: diskEncryptionSetName + location: location + identity: { + type: 'SystemAssigned' + } + properties: { + activeKey: { + sourceVault: { + id: keyVault.id + } + keyUrl: keyVault::key.properties.keyUriWithVersion + } + encryptionType: 'EncryptionAtRestWithPlatformAndCustomerKeys' + } +} + +resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(keyVault::key.id, 'Key Vault Crypto User', diskEncryptionSet.id) + scope: keyVault + properties: { + principalId: diskEncryptionSet.identity.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6') // Key Vault Crypto Service Encryption User + principalType: 'ServicePrincipal' + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource msiRGContrRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(resourceGroup().id, 'Contributor', managedIdentity.id) + scope: resourceGroup() + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + principalType: 'ServicePrincipal' + } +} + +resource sshDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: sshDeploymentScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + azPowerShellVersion: '9.0' + retentionInterval: 'P1D' + arguments: '-SSHKeyName "${sshKeyName}" -ResourceGroupName "${resourceGroup().name}"' + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/New-SSHKey.ps1') + } + dependsOn: [ + msiRGContrRoleAssignment + ] +} + +resource sshKey 'Microsoft.Compute/sshPublicKeys@2022-03-01' = { + name: sshKeyName + location: location + properties: { + publicKey: sshDeploymentScript.properties.outputs.publicKey + } +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The resource ID of the created Disk Encryption Set.') +output diskEncryptionSetResourceId string = diskEncryptionSet.id + +@description('The Public Key of the created SSH Key.') +output SSHKeyPublicKey string = sshKey.properties.publicKey diff --git a/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.ssecmk/main.test.bicep b/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.ssecmk/main.test.bicep new file mode 100644 index 0000000000..b071b2f69c --- /dev/null +++ b/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.ssecmk/main.test.bicep @@ -0,0 +1,120 @@ +targetScope = 'subscription' + +metadata name = 'Using disk encryption set for the VM.' +metadata description = 'This instance deploys the module with disk enryption set.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-compute.virtualmachinescalesets-${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 = 'cvmsslcmk' + +@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.') +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: { + location: resourceLocation + virtualNetworkName: 'dep-${namePrefix}-vnet-${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)}' + diskEncryptionSetName: 'dep-${namePrefix}-des-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + sshDeploymentScriptName: 'dep-${namePrefix}-ds-${serviceShort}' + sshKeyName: 'dep-${namePrefix}-ssh-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + extensionMonitoringAgentConfig: { + enabled: true + } + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + adminUsername: 'scaleSetAdmin' + imageReference: { + publisher: 'Canonical' + offer: '0001-com-ubuntu-server-jammy' + sku: '22_04-lts-gen2' + version: 'latest' + } + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig1' + properties: { + subnet: { + id: nestedDependencies.outputs.subnetResourceId + } + } + } + ] + nicSuffix: '-nic01' + } + ] + osDisk: { + createOption: 'fromImage' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + diskEncryptionSet: { + id: nestedDependencies.outputs.diskEncryptionSetResourceId + } + } + } + dataDisks: [ + { + caching: 'ReadOnly' + createOption: 'Empty' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + diskEncryptionSet: { + id: nestedDependencies.outputs.diskEncryptionSetResourceId + } + } + } + ] + osType: 'Linux' + skuName: 'Standard_B12ms' + disablePasswordAuthentication: true + publicKeys: [ + { + keyData: nestedDependencies.outputs.SSHKeyPublicKey + path: '/home/scaleSetAdmin/.ssh/authorized_keys' + } + ] + } +}] diff --git a/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.defaults/dependencies.bicep b/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.defaults/dependencies.bicep new file mode 100644 index 0000000000..1166415e54 --- /dev/null +++ b/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.defaults/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@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-scale-set/tests/e2e/windows.defaults/main.test.bicep b/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.defaults/main.test.bicep new file mode 100644 index 0000000000..8275ac5bef --- /dev/null +++ b/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.defaults/main.test.bicep @@ -0,0 +1,91 @@ +targetScope = 'subscription' + +metadata name = 'Using only defaults for Windows' +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}-compute.virtualmachinescalesets-${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 = 'cvmsswinmin' + +@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: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + location: resourceLocation + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + adminUsername: 'localAdminUser' + adminPassword: password + imageReference: { + publisher: 'MicrosoftWindowsServer' + offer: 'WindowsServer' + sku: '2022-datacenter-azure-edition' + version: 'latest' + } + osDisk: { + createOption: 'fromImage' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Windows' + skuName: 'Standard_B12ms' + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig1' + properties: { + subnet: { + id: nestedDependencies.outputs.subnetResourceId + } + } + } + ] + nicSuffix: '-nic01' + } + ] + } +}] diff --git a/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.max/dependencies.bicep b/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.max/dependencies.bicep new file mode 100644 index 0000000000..2b1b70bb91 --- /dev/null +++ b/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.max/dependencies.bicep @@ -0,0 +1,155 @@ +@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 + +@description('Required. The name of the Key Vault to create.') +param keyVaultName string + +@description('Required. The name of the Storage Account to create.') +param storageAccountName string + +@description('Required. The name of the Deployment Script used to upload data to the Storage Account.') +param storageUploadDeploymentScriptName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +var storageAccountCSEFileName = 'scriptExtensionMasterInstaller.ps1' +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) + } + } + ] + } +} + +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 key 'keys@2022-07-01' = { + name: 'encryptionKey' + properties: { + kty: 'RSA' + } + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource msiRGContrRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(resourceGroup().id, 'Contributor', managedIdentity.id) + scope: resourceGroup() + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + principalType: 'ServicePrincipal' + } +} + +resource msiKVCryptoUserRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(keyVault::key.id, 'Key Vault Crypto User', managedIdentity.id) + scope: keyVault::key + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User + principalType: 'ServicePrincipal' + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-09-01' = { + name: storageAccountName + location: location + sku: { + name: 'Standard_LRS' + } + kind: 'StorageV2' + + resource blobService 'blobServices@2021-09-01' = { + name: 'default' + + resource container 'containers@2021-09-01' = { + name: 'scripts' + } + } +} + +resource storageUpload 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: storageUploadDeploymentScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + azPowerShellVersion: '9.0' + retentionInterval: 'P1D' + arguments: '-StorageAccountName "${storageAccount.name}" -ResourceGroupName "${resourceGroup().name}" -ContainerName "${storageAccount::blobService::container.name}" -FileName "${storageAccountCSEFileName}"' + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/Set-BlobContent.ps1') + } + dependsOn: [ + msiRGContrRoleAssignment + ] +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].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 + +@description('The resource ID of the created Key Vault.') +output keyVaultResourceId string = keyVault.id + +@description('The URL of the created Key Vault.') +output keyVaultUrl string = keyVault.properties.vaultUri + +@description('The URL of the created Key Vault Encryption Key.') +output keyVaultEncryptionKeyUrl string = keyVault::key.properties.keyUriWithVersion + +@description('The resource ID of the created Storage Account.') +output storageAccountResourceId string = storageAccount.id + +@description('The URL of the Custom Script Extension in the created Storage Account') +output storageAccountCSEFileUrl string = '${storageAccount.properties.primaryEndpoints.blob}${storageAccount::blobService::container.name}/${storageAccountCSEFileName}' + +@description('The name of the Custom Script Extension in the created Storage Account.') +output storageAccountCSEFileName string = storageAccountCSEFileName diff --git a/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.max/main.test.bicep b/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.max/main.test.bicep new file mode 100644 index 0000000000..d3524669f6 --- /dev/null +++ b/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.max/main.test.bicep @@ -0,0 +1,205 @@ +targetScope = 'subscription' + +metadata name = 'Using large parameter set for Windows' +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}-compute.virtualmachinescalesets-${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 = 'cvmsswinmax' + +@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: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + location: resourceLocation + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}' + storageAccountName: take('dep${namePrefix}sa${serviceShort}01', 24) + storageUploadDeploymentScriptName: 'dep-${namePrefix}-sads-${serviceShort}' + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-diagnosticDependencies' + params: { + storageAccountName: take('dep${namePrefix}diasa${serviceShort}01', 24) + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}' + eventHubNamespaceName: 'dep-${namePrefix}-evhns-${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: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + adminUsername: 'localAdminUser' + imageReference: { + publisher: 'MicrosoftWindowsServer' + offer: 'WindowsServer' + sku: '2022-datacenter-azure-edition' + version: 'latest' + } + osDisk: { + createOption: 'fromImage' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Windows' + skuName: 'Standard_B12ms' + adminPassword: password + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + encryptionAtHost: false + extensionAntiMalwareConfig: { + enabled: true + settings: { + AntimalwareEnabled: true + Exclusions: { + Extensions: '.log;.ldf' + Paths: 'D:\\IISlogs;D:\\DatabaseLogs' + Processes: 'mssence.svc' + } + RealtimeProtectionEnabled: true + ScheduledScanSettings: { + day: '7' + isEnabled: 'true' + scanType: 'Quick' + time: '120' + } + } + } + extensionCustomScriptConfig: { + enabled: true + fileData: [ + { + storageAccountId: nestedDependencies.outputs.storageAccountResourceId + uri: nestedDependencies.outputs.storageAccountCSEFileUrl + } + ] + protectedSettings: { + commandToExecute: 'powershell -ExecutionPolicy Unrestricted -Command "& ./${nestedDependencies.outputs.storageAccountCSEFileName}"' + } + } + extensionDependencyAgentConfig: { + enabled: true + } + extensionAzureDiskEncryptionConfig: { + enabled: true + settings: { + EncryptionOperation: 'EnableEncryption' + KekVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + KeyEncryptionAlgorithm: 'RSA-OAEP' + KeyEncryptionKeyURL: nestedDependencies.outputs.keyVaultEncryptionKeyUrl + KeyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + KeyVaultURL: nestedDependencies.outputs.keyVaultUrl + ResizeOSDisk: 'false' + VolumeType: 'All' + } + } + extensionDSCConfig: { + enabled: true + } + extensionMonitoringAgentConfig: { + enabled: true + } + extensionNetworkWatcherAgentConfig: { + enabled: true + } + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig1' + properties: { + subnet: { + id: nestedDependencies.outputs.subnetResourceId + } + } + } + ] + nicSuffix: '-nic01' + } + ] + roleAssignments: [ + { + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + roleDefinitionIdOrName: 'Reader' + principalType: 'ServicePrincipal' + } + ] + skuCapacity: 1 + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + upgradePolicyMode: 'Manual' + vmNamePrefix: 'vmsswinvm' + vmPriority: 'Regular' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.waf-aligned/dependencies.bicep b/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.waf-aligned/dependencies.bicep new file mode 100644 index 0000000000..2b1b70bb91 --- /dev/null +++ b/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.waf-aligned/dependencies.bicep @@ -0,0 +1,155 @@ +@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 + +@description('Required. The name of the Key Vault to create.') +param keyVaultName string + +@description('Required. The name of the Storage Account to create.') +param storageAccountName string + +@description('Required. The name of the Deployment Script used to upload data to the Storage Account.') +param storageUploadDeploymentScriptName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +var storageAccountCSEFileName = 'scriptExtensionMasterInstaller.ps1' +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) + } + } + ] + } +} + +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 key 'keys@2022-07-01' = { + name: 'encryptionKey' + properties: { + kty: 'RSA' + } + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource msiRGContrRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(resourceGroup().id, 'Contributor', managedIdentity.id) + scope: resourceGroup() + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + principalType: 'ServicePrincipal' + } +} + +resource msiKVCryptoUserRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(keyVault::key.id, 'Key Vault Crypto User', managedIdentity.id) + scope: keyVault::key + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User + principalType: 'ServicePrincipal' + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-09-01' = { + name: storageAccountName + location: location + sku: { + name: 'Standard_LRS' + } + kind: 'StorageV2' + + resource blobService 'blobServices@2021-09-01' = { + name: 'default' + + resource container 'containers@2021-09-01' = { + name: 'scripts' + } + } +} + +resource storageUpload 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: storageUploadDeploymentScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + azPowerShellVersion: '9.0' + retentionInterval: 'P1D' + arguments: '-StorageAccountName "${storageAccount.name}" -ResourceGroupName "${resourceGroup().name}" -ContainerName "${storageAccount::blobService::container.name}" -FileName "${storageAccountCSEFileName}"' + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/Set-BlobContent.ps1') + } + dependsOn: [ + msiRGContrRoleAssignment + ] +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].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 + +@description('The resource ID of the created Key Vault.') +output keyVaultResourceId string = keyVault.id + +@description('The URL of the created Key Vault.') +output keyVaultUrl string = keyVault.properties.vaultUri + +@description('The URL of the created Key Vault Encryption Key.') +output keyVaultEncryptionKeyUrl string = keyVault::key.properties.keyUriWithVersion + +@description('The resource ID of the created Storage Account.') +output storageAccountResourceId string = storageAccount.id + +@description('The URL of the Custom Script Extension in the created Storage Account') +output storageAccountCSEFileUrl string = '${storageAccount.properties.primaryEndpoints.blob}${storageAccount::blobService::container.name}/${storageAccountCSEFileName}' + +@description('The name of the Custom Script Extension in the created Storage Account.') +output storageAccountCSEFileName string = storageAccountCSEFileName diff --git a/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.waf-aligned/main.test.bicep b/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.waf-aligned/main.test.bicep new file mode 100644 index 0000000000..337487ca49 --- /dev/null +++ b/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.waf-aligned/main.test.bicep @@ -0,0 +1,194 @@ +targetScope = 'subscription' + +metadata name = 'WAF-aligned' +metadata description = 'This instance deploys the module in alignment with the best-practices of the Well-Architected Framework for Windows.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-compute.virtualmachinescalesets-${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 = 'cvmsswinwaf' + +@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: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + location: resourceLocation + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}' + storageAccountName: take('dep${namePrefix}sa${serviceShort}01', 24) + storageUploadDeploymentScriptName: 'dep-${namePrefix}-sads-${serviceShort}' + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-diagnosticDependencies' + params: { + storageAccountName: take('dep${namePrefix}diasa${serviceShort}01', 24) + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}' + eventHubNamespaceName: 'dep-${namePrefix}-evhns-${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: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + adminUsername: 'localAdminUser' + imageReference: { + publisher: 'MicrosoftWindowsServer' + offer: 'WindowsServer' + sku: '2022-datacenter-azure-edition' + version: 'latest' + } + osDisk: { + createOption: 'fromImage' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Windows' + skuName: 'Standard_B12ms' + adminPassword: password + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + encryptionAtHost: false // Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your virtual machine scale sets. + extensionAntiMalwareConfig: { + enabled: true + settings: { + AntimalwareEnabled: true + Exclusions: { + Extensions: '.log;.ldf' + Paths: 'D:\\IISlogs;D:\\DatabaseLogs' + Processes: 'mssence.svc' + } + RealtimeProtectionEnabled: true + ScheduledScanSettings: { + day: '7' + isEnabled: 'true' + scanType: 'Quick' + time: '120' + } + } + } + extensionCustomScriptConfig: { + enabled: true + fileData: [ + { + storageAccountId: nestedDependencies.outputs.storageAccountResourceId + uri: nestedDependencies.outputs.storageAccountCSEFileUrl + } + ] + protectedSettings: { + commandToExecute: 'powershell -ExecutionPolicy Unrestricted -Command "& ./${nestedDependencies.outputs.storageAccountCSEFileName}"' + } + } + extensionDependencyAgentConfig: { + enabled: true + } + extensionAzureDiskEncryptionConfig: { + enabled: true + settings: { + EncryptionOperation: 'EnableEncryption' + KekVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + KeyEncryptionAlgorithm: 'RSA-OAEP' + KeyEncryptionKeyURL: nestedDependencies.outputs.keyVaultEncryptionKeyUrl + KeyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + KeyVaultURL: nestedDependencies.outputs.keyVaultUrl + ResizeOSDisk: 'false' + VolumeType: 'All' + } + } + extensionDSCConfig: { + enabled: true + } + extensionMonitoringAgentConfig: { + enabled: true + } + extensionNetworkWatcherAgentConfig: { + enabled: true + } + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig1' + properties: { + subnet: { + id: nestedDependencies.outputs.subnetResourceId + } + } + } + ] + nicSuffix: '-nic01' + } + ] + skuCapacity: 1 + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + upgradePolicyMode: 'Manual' + vmNamePrefix: 'vmsswinvm' + vmPriority: 'Regular' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/compute/virtual-machine-scale-set/version.json b/avm/res/compute/virtual-machine-scale-set/version.json new file mode 100644 index 0000000000..83083db694 --- /dev/null +++ b/avm/res/compute/virtual-machine-scale-set/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.1", + "pathFilters": [ + "./main.json" + ] +} \ No newline at end of file From b5b005b199d54b6dbc7b2a937a5d614250100a15 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Mar 2024 17:37:49 +0000 Subject: [PATCH 17/73] fix: bump actions/upload-pages-artifact from 2 to 3 (#1275) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact) from 2 to 3.

Release notes

Sourced from actions/upload-pages-artifact's releases.

v3.0.0

Changelog

To deploy a GitHub Pages site which has been uploaded with this version of actions/upload-pages-artifact, you must also use actions/deploy-pages@v4 or newer.

See details of all code changes since previous release.

Commits
  • 56afc60 Merge pull request #94 from SilverRainZ/main
  • d12fdfb Merge branch 'main' into main
  • aef5542 Merge pull request #88 from uiolee/patch-1
  • 29cedd7 Merge branch 'main' into patch-1
  • a69c22e Merge pull request #92 from actions/dependabot/github_actions/non-breaking-ch...
  • 794e304 Group tar's output to prevent it from messing up logs
  • 14007f6 Bump the non-breaking-changes group with 1 update
  • 0191170 Merge pull request #91 from actions/dependabot-grouping
  • 0e7832d Update Dependabot config to group non-breaking changes
  • 1a6d9fa Update README.md
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/upload-pages-artifact&package-manager=github_actions&previous-version=2&new-version=3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish-module-index.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-module-index.yml b/.github/workflows/publish-module-index.yml index 219696d3cf..fa3317ea29 100644 --- a/.github/workflows/publish-module-index.yml +++ b/.github/workflows/publish-module-index.yml @@ -102,7 +102,7 @@ jobs: JEKYLL_ENV: production - name: Upload Pages artifact - uses: actions/upload-pages-artifact@v2 + uses: actions/upload-pages-artifact@v3 with: path: ./docs/jekyll/_site From 8dddc05e6791bb20fab6fd6571d4ef6aa4281004 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Mar 2024 17:39:51 +0000 Subject: [PATCH 18/73] fix: bump azure/login from 1 to 2 (#1274) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [azure/login](https://github.com/azure/login) from 1 to 2.
Release notes

Sourced from azure/login's releases.

Azure Login Action v2

What's Changed

New Contributors

Full Changelog: https://github.com/Azure/login/compare/v1.6.1...v2

Azure Login Action v1.6.1

  • Fix #403: Do not break the workflow if az is not installed in pre and post steps

Azure Login Action v1.6.0

  • Added pre: and post: action for cleaning up (#384)

Azure Login Action v1.5.1

  • Fixed #371: Allow optional subscriptionId in creds (#373)
  • Cleaned accounts before login (#376, #377)
  • Updated actions-secret-parser from 1.0.2 to 1.0.4 (#378)

Azure Login Action v1.5.0

  • Updated the versions of dependencies.
  • Supported passwords to start with hyphen(-).
  • Enabled OIDC for sovereign clouds.
  • Supported Managed Identity Login.

[BUG FIX] Version pattern regex update

No release notes provided.

Handling id-token error and Node version upgradation

In this release, a separate error will be thrown if id-token permissions are not set in the workflow for OIDC login. Also upgraded the Node version to 16.

Handling warnings and added OIDC promotional note.

Error handling and minor doc changes.

Added az installation requirement in the error response

No release notes provided.

Added federated token details in logs

Displaying OIDC token details - subject claim and issuer in the logs.

Added audience parameter and CLI,PS logs

An explicit input parameter called audience is added to allow the option provided in the azure portal. Also CLI and powershell errors are being surfaced inside the action.

Added OIDC support

Login Action now supports two different ways of authentication with Azure. One using the Azure Service Principal with secrets. We now added the new OpenID Connect (OIDC) method of authentication using Azure Service Principal with a Federated Identity Credential.

Adding Azure PowerShell login changes

With the Azure login Action, you can automate your workflow to do an Azure login using Azure service principal and run Az CLI and Azure PowerShell scripts.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=azure/login&package-manager=github_actions&previous-version=1&new-version=2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/avm.platform.publish-tag.yml | 2 +- .github/workflows/publish-module-index.yml | 2 +- .github/workflows/publish-module.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/avm.platform.publish-tag.yml b/.github/workflows/avm.platform.publish-tag.yml index e18574d79a..3f1488ebd3 100644 --- a/.github/workflows/avm.platform.publish-tag.yml +++ b/.github/workflows/avm.platform.publish-tag.yml @@ -26,7 +26,7 @@ jobs: uses: ./.github/actions/templates/avm-setEnvironment - name: Log in to Azure - uses: azure/login@v1 + uses: azure/login@v2 with: client-id: "${{ secrets.PUBLISH_CLIENT_ID }}" tenant-id: "${{ secrets.PUBLISH_TENANT_ID }}" diff --git a/.github/workflows/publish-module-index.yml b/.github/workflows/publish-module-index.yml index fa3317ea29..3d3523adc5 100644 --- a/.github/workflows/publish-module-index.yml +++ b/.github/workflows/publish-module-index.yml @@ -43,7 +43,7 @@ jobs: path: moduleIndex.json - name: Log in to Azure - uses: azure/login@v1 + uses: azure/login@v2 with: client-id: ${{ secrets.PUBLISH_CLIENT_ID }} tenant-id: ${{ secrets.PUBLISH_TENANT_ID }} diff --git a/.github/workflows/publish-module.yml b/.github/workflows/publish-module.yml index 10271adcae..d573607b20 100644 --- a/.github/workflows/publish-module.yml +++ b/.github/workflows/publish-module.yml @@ -54,7 +54,7 @@ jobs: ref: ${{ github.event.inputs.tag || inputs.tag }} - name: Log in to Azure - uses: azure/login@v1 + uses: azure/login@v2 with: client-id: ${{ secrets.PUBLISH_CLIENT_ID }} tenant-id: ${{ secrets.PUBLISH_TENANT_ID }} From ddc5f5fb0293aa78b8b0a24644b5f99e8d1e6ce4 Mon Sep 17 00:00:00 2001 From: Alexander Sehr Date: Wed, 13 Mar 2024 14:58:01 -0400 Subject: [PATCH 19/73] Users/alsehr/token regex fix (#1276) ## Description Fixed fail-safe regex (added missing escapes). Until now, `--------` would cause an issue, even though we're only interested in `-..--..-`. Output for Azure-Firewall with default behavior: ![image](https://github.com/Azure/bicep-registry-modules/assets/5365358/37d63bb9-73c0-4809-bc73-497e402d3775) Output for Azure Firewall with disabled token replacement (to validate the fail-safe works): ![image](https://github.com/Azure/bicep-registry-modules/assets/5365358/291a842f-4689-4cc7-9520-746a60d43244) ## Pipeline Reference | Pipeline | | -------- | | | ## Type of Change - [x] Update to CI Environment or utlities (Non-module effecting changes) - [ ] Azure Verified Module updates: - [ ] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation --------- Co-authored-by: Erika Gressi <56914614+eriqua@users.noreply.github.com> --- avm/res/network/azure-firewall/README.md | 34 +++++++++---------- avm/res/network/azure-firewall/main.bicep | 8 ++--- avm/res/network/azure-firewall/main.json | 8 ++--- .../tests/e2e/addpip/main.test.bicep | 2 +- .../tests/e2e/custompip/main.test.bicep | 2 +- .../tests/e2e/defaults/main.test.bicep | 2 +- .../tests/e2e/max/main.test.bicep | 2 +- .../tests/e2e/waf-aligned/main.test.bicep | 2 +- avm/res/network/bastion-host/README.md | 30 ++++++++-------- avm/res/network/bastion-host/main.bicep | 6 ++-- avm/res/network/bastion-host/main.json | 8 ++--- .../tests/e2e/custompip/main.test.bicep | 2 +- .../tests/e2e/defaults/main.test.bicep | 2 +- .../tests/e2e/max/main.test.bicep | 2 +- .../tests/e2e/waf-aligned/main.test.bicep | 2 +- avm/res/network/bastion-host/version.json | 2 +- avm/res/network/virtual-network/main.bicep | 16 ++++----- avm/res/network/virtual-network/main.json | 12 ++----- avm/res/network/virtual-network/version.json | 2 +- .../publish/Publish-ModuleFromPathToPBR.ps1 | 6 ++-- 20 files changed, 70 insertions(+), 80 deletions(-) diff --git a/avm/res/network/azure-firewall/README.md b/avm/res/network/azure-firewall/README.md index fbb0980ca3..1a450e250b 100644 --- a/avm/res/network/azure-firewall/README.md +++ b/avm/res/network/azure-firewall/README.md @@ -71,7 +71,7 @@ module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { } ] } - virtualNetworkId: '' + virtualNetworkResourceId: '' } } ``` @@ -119,8 +119,8 @@ module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { ] } }, - "virtualNetworkId": { - "value": "" + "virtualNetworkResourceId": { + "value": "" } } } @@ -174,7 +174,7 @@ module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { skuName: 'Standard' skuTier: 'Regional' } - virtualNetworkId: '' + virtualNetworkResourceId: '' } } ``` @@ -229,8 +229,8 @@ module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { "skuTier": "Regional" } }, - "virtualNetworkId": { - "value": "" + "virtualNetworkResourceId": { + "value": "" } } } @@ -256,7 +256,7 @@ module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { name: 'nafmin001' // Non-required parameters location: '' - virtualNetworkId: '' + virtualNetworkResourceId: '' } } ``` @@ -281,8 +281,8 @@ module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { "location": { "value": "" }, - "virtualNetworkId": { - "value": "" + "virtualNetworkResourceId": { + "value": "" } } } @@ -562,7 +562,7 @@ module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { 'hidden-title': 'This is visible in the resource name' Role: 'DeploymentValidation' } - virtualNetworkId: '' + virtualNetworkResourceId: '' zones: [ '1' '2' @@ -728,8 +728,8 @@ module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { "Role": "DeploymentValidation" } }, - "virtualNetworkId": { - "value": "" + "virtualNetworkResourceId": { + "value": "" }, "zones": { "value": [ @@ -863,7 +863,7 @@ module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { 'hidden-title': 'This is visible in the resource name' Role: 'DeploymentValidation' } - virtualNetworkId: '' + virtualNetworkResourceId: '' zones: [ '1' '2' @@ -1004,8 +1004,8 @@ module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { "Role": "DeploymentValidation" } }, - "virtualNetworkId": { - "value": "" + "virtualNetworkResourceId": { + "value": "" }, "zones": { "value": [ @@ -1036,7 +1036,7 @@ module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { | :-- | :-- | :-- | | [`hubIPAddresses`](#parameter-hubipaddresses) | object | IP addresses associated with AzureFirewall. Required if `virtualHubId` is supplied. | | [`virtualHubId`](#parameter-virtualhubid) | string | The virtualHub resource ID to which the firewall belongs. Required if `virtualNetworkId` is empty. | -| [`virtualNetworkId`](#parameter-virtualnetworkid) | string | Shared services Virtual Network resource ID. The virtual network ID containing AzureFirewallSubnet. If a Public IP is not provided, then the Public IP that is created as part of this module will be applied with the subnet provided in this variable. Required if `virtualHubId` is empty. | +| [`virtualNetworkResourceId`](#parameter-virtualnetworkresourceid) | string | Shared services Virtual Network resource ID. The virtual network ID containing AzureFirewallSubnet. If a Public IP is not provided, then the Public IP that is created as part of this module will be applied with the subnet provided in this variable. Required if `virtualHubId` is empty. | **Optional parameters** @@ -1084,7 +1084,7 @@ The virtualHub resource ID to which the firewall belongs. Required if `virtualNe - Type: string - Default: `''` -### Parameter: `virtualNetworkId` +### Parameter: `virtualNetworkResourceId` Shared services Virtual Network resource ID. The virtual network ID containing AzureFirewallSubnet. If a Public IP is not provided, then the Public IP that is created as part of this module will be applied with the subnet provided in this variable. Required if `virtualHubId` is empty. diff --git a/avm/res/network/azure-firewall/main.bicep b/avm/res/network/azure-firewall/main.bicep index df64924d31..f0edf1142c 100644 --- a/avm/res/network/azure-firewall/main.bicep +++ b/avm/res/network/azure-firewall/main.bicep @@ -14,7 +14,7 @@ param name string param azureSkuTier string = 'Standard' @description('Conditional. Shared services Virtual Network resource ID. The virtual network ID containing AzureFirewallSubnet. If a Public IP is not provided, then the Public IP that is created as part of this module will be applied with the subnet provided in this variable. Required if `virtualHubId` is empty.') -param virtualNetworkId string = '' +param virtualNetworkResourceId string = '' @description('Optional. The Public IP resource ID to associate to the AzureFirewallSubnet. If empty, then the Public IP that is created as part of this module will be applied to the AzureFirewallSubnet.') param publicIPResourceID string = '' @@ -84,7 +84,7 @@ param tags object? @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -var azureSkuName = empty(virtualNetworkId) ? 'AZFW_Hub' : 'AZFW_VNet' +var azureSkuName = empty(virtualNetworkResourceId) ? 'AZFW_Hub' : 'AZFW_VNet' var requiresManagementIp = azureSkuTier == 'Basic' ? true : false var isCreateDefaultManagementIP = empty(managementIPResourceID) && requiresManagementIp @@ -107,7 +107,7 @@ var ipConfigurations = concat([ name: !empty(publicIPResourceID) ? last(split(publicIPResourceID, '/')) : publicIPAddress.outputs.name properties: union({ subnet: { - id: '${virtualNetworkId}/subnets/AzureFirewallSubnet' // The subnet name must be AzureFirewallSubnet + id: '${virtualNetworkResourceId}/subnets/AzureFirewallSubnet' // The subnet name must be AzureFirewallSubnet } }, (!empty(publicIPResourceID) || !empty(publicIPAddressObject)) ? { //Use existing Public IP, new Public IP created in this module, or none if neither @@ -127,7 +127,7 @@ var managementIPConfiguration = { name: !empty(managementIPResourceID) ? last(split(managementIPResourceID, '/')) : managementIPAddress.outputs.name properties: union({ subnet: { - id: '${virtualNetworkId}/subnets/AzureFirewallManagementSubnet' // The subnet name must be AzureFirewallManagementSubnet for a 'Basic' SKU tier firewall + id: '${virtualNetworkResourceId}/subnets/AzureFirewallManagementSubnet' // The subnet name must be AzureFirewallManagementSubnet for a 'Basic' SKU tier firewall } }, (!empty(publicIPResourceID) || !empty(managementIPAddressObject)) ? { // Use existing Management Public IP, new Management Public IP created in this module, or none if neither diff --git a/avm/res/network/azure-firewall/main.json b/avm/res/network/azure-firewall/main.json index 0d3a43ef89..27aaafd57d 100644 --- a/avm/res/network/azure-firewall/main.json +++ b/avm/res/network/azure-firewall/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "1020924055893877667" + "templateHash": "4205211650529288648" }, "name": "Azure Firewalls", "description": "This module deploys an Azure Firewall.", @@ -244,7 +244,7 @@ "description": "Optional. Tier of an Azure Firewall." } }, - "virtualNetworkId": { + "virtualNetworkResourceId": { "type": "string", "defaultValue": "", "metadata": { @@ -406,7 +406,7 @@ } } ], - "azureSkuName": "[if(empty(parameters('virtualNetworkId')), 'AZFW_Hub', 'AZFW_VNet')]", + "azureSkuName": "[if(empty(parameters('virtualNetworkResourceId')), 'AZFW_Hub', 'AZFW_VNet')]", "requiresManagementIp": "[if(equals(parameters('azureSkuTier'), 'Basic'), true(), false())]", "isCreateDefaultManagementIP": "[and(empty(parameters('managementIPResourceID')), variables('requiresManagementIp'))]", "builtInRoleNames": { @@ -445,7 +445,7 @@ "location": "[parameters('location')]", "zones": "[if(equals(length(parameters('zones')), 0), null(), parameters('zones'))]", "tags": "[parameters('tags')]", - "properties": "[if(equals(variables('azureSkuName'), 'AZFW_VNet'), createObject('threatIntelMode', parameters('threatIntelMode'), 'firewallPolicy', if(not(empty(parameters('firewallPolicyId'))), createObject('id', parameters('firewallPolicyId')), null()), 'ipConfigurations', concat(createArray(createObject('name', if(not(empty(parameters('publicIPResourceID'))), last(split(parameters('publicIPResourceID'), '/')), reference('publicIPAddress').outputs.name.value), 'properties', union(createObject('subnet', createObject('id', format('{0}/subnets/AzureFirewallSubnet', parameters('virtualNetworkId')))), if(or(not(empty(parameters('publicIPResourceID'))), not(empty(parameters('publicIPAddressObject')))), createObject('publicIPAddress', createObject('id', if(not(empty(parameters('publicIPResourceID'))), parameters('publicIPResourceID'), reference('publicIPAddress').outputs.resourceId.value))), createObject())))), variables('additionalPublicIpConfigurationsVar')), 'managementIpConfiguration', if(variables('requiresManagementIp'), createObject('name', if(not(empty(parameters('managementIPResourceID'))), last(split(parameters('managementIPResourceID'), '/')), reference('managementIPAddress').outputs.name.value), 'properties', union(createObject('subnet', createObject('id', format('{0}/subnets/AzureFirewallManagementSubnet', parameters('virtualNetworkId')))), if(or(not(empty(parameters('publicIPResourceID'))), not(empty(parameters('managementIPAddressObject')))), createObject('publicIPAddress', createObject('id', if(not(empty(parameters('managementIPResourceID'))), parameters('managementIPResourceID'), reference('managementIPAddress').outputs.resourceId.value))), createObject()))), null()), 'sku', createObject('name', variables('azureSkuName'), 'tier', parameters('azureSkuTier')), 'applicationRuleCollections', parameters('applicationRuleCollections'), 'natRuleCollections', parameters('natRuleCollections'), 'networkRuleCollections', parameters('networkRuleCollections')), createObject('firewallPolicy', if(not(empty(parameters('firewallPolicyId'))), createObject('id', parameters('firewallPolicyId')), null()), 'sku', createObject('name', variables('azureSkuName'), 'tier', parameters('azureSkuTier')), 'hubIPAddresses', if(not(empty(parameters('hubIPAddresses'))), parameters('hubIPAddresses'), null()), 'virtualHub', if(not(empty(parameters('virtualHubId'))), createObject('id', parameters('virtualHubId')), null())))]", + "properties": "[if(equals(variables('azureSkuName'), 'AZFW_VNet'), createObject('threatIntelMode', parameters('threatIntelMode'), 'firewallPolicy', if(not(empty(parameters('firewallPolicyId'))), createObject('id', parameters('firewallPolicyId')), null()), 'ipConfigurations', concat(createArray(createObject('name', if(not(empty(parameters('publicIPResourceID'))), last(split(parameters('publicIPResourceID'), '/')), reference('publicIPAddress').outputs.name.value), 'properties', union(createObject('subnet', createObject('id', format('{0}/subnets/AzureFirewallSubnet', parameters('virtualNetworkResourceId')))), if(or(not(empty(parameters('publicIPResourceID'))), not(empty(parameters('publicIPAddressObject')))), createObject('publicIPAddress', createObject('id', if(not(empty(parameters('publicIPResourceID'))), parameters('publicIPResourceID'), reference('publicIPAddress').outputs.resourceId.value))), createObject())))), variables('additionalPublicIpConfigurationsVar')), 'managementIpConfiguration', if(variables('requiresManagementIp'), createObject('name', if(not(empty(parameters('managementIPResourceID'))), last(split(parameters('managementIPResourceID'), '/')), reference('managementIPAddress').outputs.name.value), 'properties', union(createObject('subnet', createObject('id', format('{0}/subnets/AzureFirewallManagementSubnet', parameters('virtualNetworkResourceId')))), if(or(not(empty(parameters('publicIPResourceID'))), not(empty(parameters('managementIPAddressObject')))), createObject('publicIPAddress', createObject('id', if(not(empty(parameters('managementIPResourceID'))), parameters('managementIPResourceID'), reference('managementIPAddress').outputs.resourceId.value))), createObject()))), null()), 'sku', createObject('name', variables('azureSkuName'), 'tier', parameters('azureSkuTier')), 'applicationRuleCollections', parameters('applicationRuleCollections'), 'natRuleCollections', parameters('natRuleCollections'), 'networkRuleCollections', parameters('networkRuleCollections')), createObject('firewallPolicy', if(not(empty(parameters('firewallPolicyId'))), createObject('id', parameters('firewallPolicyId')), null()), 'sku', createObject('name', variables('azureSkuName'), 'tier', parameters('azureSkuTier')), 'hubIPAddresses', if(not(empty(parameters('hubIPAddresses'))), parameters('hubIPAddresses'), null()), 'virtualHub', if(not(empty(parameters('virtualHubId'))), createObject('id', parameters('virtualHubId')), null())))]", "dependsOn": [ "managementIPAddress", "publicIPAddress" diff --git a/avm/res/network/azure-firewall/tests/e2e/addpip/main.test.bicep b/avm/res/network/azure-firewall/tests/e2e/addpip/main.test.bicep index 4a27824896..28f977e678 100644 --- a/avm/res/network/azure-firewall/tests/e2e/addpip/main.test.bicep +++ b/avm/res/network/azure-firewall/tests/e2e/addpip/main.test.bicep @@ -53,7 +53,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' params: { location: resourceLocation name: '${namePrefix}${serviceShort}001' - virtualNetworkId: nestedDependencies.outputs.virtualNetworkResourceId + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId additionalPublicIpConfigurations: [ { name: 'ipConfig01' diff --git a/avm/res/network/azure-firewall/tests/e2e/custompip/main.test.bicep b/avm/res/network/azure-firewall/tests/e2e/custompip/main.test.bicep index e201b2d21f..2891ccb851 100644 --- a/avm/res/network/azure-firewall/tests/e2e/custompip/main.test.bicep +++ b/avm/res/network/azure-firewall/tests/e2e/custompip/main.test.bicep @@ -66,7 +66,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' params: { location: resourceLocation name: '${namePrefix}${serviceShort}001' - virtualNetworkId: nestedDependencies.outputs.virtualNetworkResourceId + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId publicIPAddressObject: { name: 'new-${namePrefix}-pip-${serviceShort}' publicIPAllocationMethod: 'Static' diff --git a/avm/res/network/azure-firewall/tests/e2e/defaults/main.test.bicep b/avm/res/network/azure-firewall/tests/e2e/defaults/main.test.bicep index 8ec00541a0..623ae364cb 100644 --- a/avm/res/network/azure-firewall/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/azure-firewall/tests/e2e/defaults/main.test.bicep @@ -50,7 +50,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' params: { name: '${namePrefix}${serviceShort}001' - virtualNetworkId: nestedDependencies.outputs.virtualNetworkResourceId + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId location: resourceLocation } }] diff --git a/avm/res/network/azure-firewall/tests/e2e/max/main.test.bicep b/avm/res/network/azure-firewall/tests/e2e/max/main.test.bicep index 51b94e2234..c3c6ca138f 100644 --- a/avm/res/network/azure-firewall/tests/e2e/max/main.test.bicep +++ b/avm/res/network/azure-firewall/tests/e2e/max/main.test.bicep @@ -67,7 +67,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' params: { location: resourceLocation name: '${namePrefix}${serviceShort}001' - virtualNetworkId: nestedDependencies.outputs.virtualNetworkResourceId + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId applicationRuleCollections: [ { name: 'allow-app-rules' diff --git a/avm/res/network/azure-firewall/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/azure-firewall/tests/e2e/waf-aligned/main.test.bicep index 524ca25f25..61cca78551 100644 --- a/avm/res/network/azure-firewall/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/azure-firewall/tests/e2e/waf-aligned/main.test.bicep @@ -67,7 +67,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' params: { location: resourceLocation name: '${namePrefix}${serviceShort}001' - virtualNetworkId: nestedDependencies.outputs.virtualNetworkResourceId + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId applicationRuleCollections: [ { name: 'allow-app-rules' diff --git a/avm/res/network/bastion-host/README.md b/avm/res/network/bastion-host/README.md index 70bf4d00ce..15f3229fbe 100644 --- a/avm/res/network/bastion-host/README.md +++ b/avm/res/network/bastion-host/README.md @@ -49,7 +49,7 @@ module bastionHost 'br/public:avm/res/network/bastion-host:' = { params: { // Required parameters name: 'nbhctmpip001' - vNetId: '' + virtualNetworkResourceId: '' // Non-required parameters location: '' publicIPAddressObject: { @@ -110,8 +110,8 @@ module bastionHost 'br/public:avm/res/network/bastion-host:' = { "name": { "value": "nbhctmpip001" }, - "vNetId": { - "value": "" + "virtualNetworkResourceId": { + "value": "" }, // Non-required parameters "location": { @@ -179,7 +179,7 @@ module bastionHost 'br/public:avm/res/network/bastion-host:' = { params: { // Required parameters name: 'nbhmin001' - vNetId: '' + virtualNetworkResourceId: '' // Non-required parameters location: '' } @@ -202,8 +202,8 @@ module bastionHost 'br/public:avm/res/network/bastion-host:' = { "name": { "value": "nbhmin001" }, - "vNetId": { - "value": "" + "virtualNetworkResourceId": { + "value": "" }, // Non-required parameters "location": { @@ -231,7 +231,7 @@ module bastionHost 'br/public:avm/res/network/bastion-host:' = { params: { // Required parameters name: 'nbhmax001' - vNetId: '' + virtualNetworkResourceId: '' // Non-required parameters bastionSubnetPublicIpResourceId: '' diagnosticSettings: [ @@ -296,8 +296,8 @@ module bastionHost 'br/public:avm/res/network/bastion-host:' = { "name": { "value": "nbhmax001" }, - "vNetId": { - "value": "" + "virtualNetworkResourceId": { + "value": "" }, // Non-required parameters "bastionSubnetPublicIpResourceId": { @@ -389,7 +389,7 @@ module bastionHost 'br/public:avm/res/network/bastion-host:' = { params: { // Required parameters name: 'nbhwaf001' - vNetId: '' + virtualNetworkResourceId: '' // Non-required parameters bastionSubnetPublicIpResourceId: '' diagnosticSettings: [ @@ -433,8 +433,8 @@ module bastionHost 'br/public:avm/res/network/bastion-host:' = { "name": { "value": "nbhwaf001" }, - "vNetId": { - "value": "" + "virtualNetworkResourceId": { + "value": "" }, // Non-required parameters "bastionSubnetPublicIpResourceId": { @@ -494,7 +494,7 @@ module bastionHost 'br/public:avm/res/network/bastion-host:' = { | Parameter | Type | Description | | :-- | :-- | :-- | | [`name`](#parameter-name) | string | Name of the Azure Bastion resource. | -| [`vNetId`](#parameter-vnetid) | string | Shared services Virtual Network resource identifier. | +| [`virtualNetworkResourceId`](#parameter-virtualnetworkresourceid) | string | Shared services Virtual Network resource Id. | **Optional parameters** @@ -523,9 +523,9 @@ Name of the Azure Bastion resource. - Required: Yes - Type: string -### Parameter: `vNetId` +### Parameter: `virtualNetworkResourceId` -Shared services Virtual Network resource identifier. +Shared services Virtual Network resource Id. - Required: Yes - Type: string diff --git a/avm/res/network/bastion-host/main.bicep b/avm/res/network/bastion-host/main.bicep index 61acff82d1..c7e49dc622 100644 --- a/avm/res/network/bastion-host/main.bicep +++ b/avm/res/network/bastion-host/main.bicep @@ -8,8 +8,8 @@ param name string @description('Optional. Location for all resources.') param location string = resourceGroup().location -@description('Required. Shared services Virtual Network resource identifier.') -param vNetId string +@description('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.') param bastionSubnetPublicIpResourceId string = '' @@ -68,7 +68,7 @@ var ipConfigurations = [ name: 'IpConfAzureBastionSubnet' properties: union({ subnet: { - id: '${vNetId}/subnets/AzureBastionSubnet' // The subnet name must be AzureBastionSubnet + id: '${virtualNetworkResourceId}/subnets/AzureBastionSubnet' // The subnet name must be AzureBastionSubnet } }, { //Use existing Public IP, new Public IP created in this module diff --git a/avm/res/network/bastion-host/main.json b/avm/res/network/bastion-host/main.json index 3902a1b7fd..d16ef2479c 100644 --- a/avm/res/network/bastion-host/main.json +++ b/avm/res/network/bastion-host/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "17052449880021967417" + "templateHash": "403145241490619459" }, "name": "Bastion Hosts", "description": "This module deploys a Bastion Host.", @@ -214,10 +214,10 @@ "description": "Optional. Location for all resources." } }, - "vNetId": { + "virtualNetworkResourceId": { "type": "string", "metadata": { - "description": "Required. Shared services Virtual Network resource identifier." + "description": "Required. Shared services Virtual Network resource Id." } }, "bastionSubnetPublicIpResourceId": { @@ -361,7 +361,7 @@ "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('vNetId')))), 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()))]", + "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()))]", "dependsOn": [ "publicIPAddress" ] 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 a3fd490ef2..7aaeca854b 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 @@ -66,7 +66,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' params: { name: '${namePrefix}${serviceShort}001' location: resourceLocation - vNetId: nestedDependencies.outputs.virtualNetworkResourceId + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId publicIPAddressObject: { name: '${namePrefix}${serviceShort}001-pip' allocationMethod: 'Static' 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 4cfee495f8..27e87ef3c2 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 @@ -51,7 +51,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' params: { name: '${namePrefix}${serviceShort}001' location: resourceLocation - vNetId: nestedDependencies.outputs.virtualNetworkResourceId + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId } dependsOn: [ nestedDependencies 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 3bca75080b..fb76689996 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 @@ -67,7 +67,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' params: { name: '${namePrefix}${serviceShort}001' location: resourceLocation - vNetId: nestedDependencies.outputs.virtualNetworkResourceId + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId bastionSubnetPublicIpResourceId: nestedDependencies.outputs.publicIPResourceId diagnosticSettings: [ { 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 fa5beb4653..ac7d900ba9 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 @@ -66,7 +66,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' params: { name: '${namePrefix}${serviceShort}001' location: resourceLocation - vNetId: nestedDependencies.outputs.virtualNetworkResourceId + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId bastionSubnetPublicIpResourceId: nestedDependencies.outputs.publicIPResourceId diagnosticSettings: [ { diff --git a/avm/res/network/bastion-host/version.json b/avm/res/network/bastion-host/version.json index 83083db694..1c035df49f 100644 --- a/avm/res/network/bastion-host/version.json +++ b/avm/res/network/bastion-host/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/network/virtual-network/main.bicep b/avm/res/network/virtual-network/main.bicep index 99be2a2f8c..5a8eaf6be6 100644 --- a/avm/res/network/virtual-network/main.bicep +++ b/avm/res/network/virtual-network/main.bicep @@ -52,14 +52,6 @@ param tags object? @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -var dnsServersVar = { - dnsServers: array(dnsServers) -} - -var ddosProtectionPlan = { - id: ddosProtectionPlanResourceId -} - var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') @@ -99,8 +91,12 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { addressSpace: { addressPrefixes: addressPrefixes } - ddosProtectionPlan: !empty(ddosProtectionPlanResourceId) ? ddosProtectionPlan : null - dhcpOptions: !empty(dnsServers) ? dnsServersVar : null + ddosProtectionPlan: !empty(ddosProtectionPlanResourceId) ? { + id: ddosProtectionPlanResourceId + } : null + dhcpOptions: !empty(dnsServers) ? { + dnsServers: array(dnsServers) + } : null enableDdosProtection: !empty(ddosProtectionPlanResourceId) encryption: vnetEncryption == true ? { enabled: vnetEncryption diff --git a/avm/res/network/virtual-network/main.json b/avm/res/network/virtual-network/main.json index eec6da87bf..755e75f48d 100644 --- a/avm/res/network/virtual-network/main.json +++ b/avm/res/network/virtual-network/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "17055439590426138357" + "templateHash": "10848130532872395336" }, "name": "Virtual Networks", "description": "This module deploys a Virtual Network (vNet).", @@ -333,12 +333,6 @@ } }, "variables": { - "dnsServersVar": { - "dnsServers": "[array(parameters('dnsServers'))]" - }, - "ddosProtectionPlan": { - "id": "[parameters('ddosProtectionPlanResourceId')]" - }, "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", @@ -402,8 +396,8 @@ "addressSpace": { "addressPrefixes": "[parameters('addressPrefixes')]" }, - "ddosProtectionPlan": "[if(not(empty(parameters('ddosProtectionPlanResourceId'))), variables('ddosProtectionPlan'), null())]", - "dhcpOptions": "[if(not(empty(parameters('dnsServers'))), variables('dnsServersVar'), 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())]" diff --git a/avm/res/network/virtual-network/version.json b/avm/res/network/virtual-network/version.json index 8def869ede..1c884ecaa9 100644 --- a/avm/res/network/virtual-network/version.json +++ b/avm/res/network/virtual-network/version.json @@ -4,4 +4,4 @@ "pathFilters": [ "./main.json" ] -} +} \ No newline at end of file diff --git a/avm/utilities/pipelines/publish/Publish-ModuleFromPathToPBR.ps1 b/avm/utilities/pipelines/publish/Publish-ModuleFromPathToPBR.ps1 index 953521d606..d66f55502f 100644 --- a/avm/utilities/pipelines/publish/Publish-ModuleFromPathToPBR.ps1 +++ b/avm/utilities/pipelines/publish/Publish-ModuleFromPathToPBR.ps1 @@ -77,11 +77,11 @@ function Publish-ModuleFromPathToPBR { $null = Convert-TokensInFileList @tokenConfiguration # Double-check that tokens are correctly replaced - $templateContent = Get-Content -Path $moduleBicepFilePath + $templateContent = bicep build $moduleBicepFilePath --stdout $incorrectLines = @() for ($index = 0; $index -lt $templateContent.Count; $index++) { - if ($templateContent[$index] -match '-..--..-') { - $incorrectLines += ('You have the token [{0}] in line [{1}] of file [{2}]. Please seek advice from the AVM team.' -f $matches[0], ($index + 1), $moduleBicepFilePath) + if ($templateContent[$index] -match '\-\.\.-\-\.\.\-') { + $incorrectLines += ('You have the token [{0}] in line [{1}] of the compiled Bicep file [{2}]. Please seek advice from the AVM team.' -f $matches[0], ($index + 1), $moduleBicepFilePath) } } if ($incorrectLines) { From c7a108fcb16117ea419a03662ffadb0c9f3695e0 Mon Sep 17 00:00:00 2001 From: Kris Baranek Date: Thu, 14 Mar 2024 09:23:02 +0100 Subject: [PATCH 20/73] fix: unorphaned `avm/res/insights/metric-alert` (#1265) ## Description Unorphaned `avm/res/insights/metric-alert` module. ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.insights.metric-alert](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.insights.metric-alert.yml/badge.svg?branch=users%2Fkrbar%2FunorphanMetricAlert)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.insights.metric-alert.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [x] Azure Verified Module updates: - [x] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [x] I have run `Set-AVMModule` locally to generate the supporting module files. - [x] My corresponding pipelines / checks run clean and green without any errors or warnings --- avm/res/insights/metric-alert/ORPHANED.md | 4 ---- avm/res/insights/metric-alert/README.md | 5 ----- 2 files changed, 9 deletions(-) delete mode 100644 avm/res/insights/metric-alert/ORPHANED.md diff --git a/avm/res/insights/metric-alert/ORPHANED.md b/avm/res/insights/metric-alert/ORPHANED.md deleted file mode 100644 index ef8fa911d2..0000000000 --- a/avm/res/insights/metric-alert/ORPHANED.md +++ /dev/null @@ -1,4 +0,0 @@ -⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ - -- Only security and bug fixes are being handled by the AVM core team at present. -- If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! \ No newline at end of file diff --git a/avm/res/insights/metric-alert/README.md b/avm/res/insights/metric-alert/README.md index 087a604a65..ab28f9a3d5 100644 --- a/avm/res/insights/metric-alert/README.md +++ b/avm/res/insights/metric-alert/README.md @@ -1,10 +1,5 @@ # Metric Alerts `[Microsoft.Insights/metricAlerts]` -> ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ -> -> - Only security and bug fixes are being handled by the AVM core team at present. -> - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! - This module deploys a Metric Alert. ## Navigation From 0d5ef60c0e01d60ef6c0ad8aec0206c3c1cdebb5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 10:27:58 +0000 Subject: [PATCH 21/73] fix: bump actions/deploy-pages from 2 to 4 (#734) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/deploy-pages](https://github.com/actions/deploy-pages) from 2 to 4.
Release notes

Sourced from actions/deploy-pages's releases.

v4.0.0

Changelog


:warning: This version of actions/deploy-pages is ONLY compatible with artifacts uploaded by either:

See details of all code changes since previous release.

:warning: For use with products other than GitHub.com, such as GitHub Enterprise Server, please consult the compatibility table.

v3.0.1

Changelog

🧰 Maintenance


See details of all code changes since previous release.

:warning: For use with products other than GitHub.com, such as GitHub Enterprise Server, please consult the compatibility table.

v3.0.0

Changelog


See details of all code changes since previous release.

:warning: For use with products other than GitHub.com, such as GitHub Enterprise Server, please consult the compatibility table.

v2.0.5

Changelog

... (truncated)

Commits
  • f33f41b Merge pull request #279 from actions/artifacts-next-ga
  • 0d45f33 pretty
  • d1e23d0 Merge branch 'main' into artifacts-next-ga
  • 13b55b3 Merge pull request #272 from kbdharun/main
  • c284911 chore/docs: update version, fix typos
  • ae44070 Merge pull request #266 from actions/dependabot/npm_and_yarn/eslint-8.55.0
  • 34a8f60 Bump eslint from 8.54.0 to 8.55.0
  • b65643c Merge pull request #267 from actions/dependabot/npm_and_yarn/nock-13.4.0
  • faceed1 Bump nock from 13.3.8 to 13.4.0
  • 230466c Merge pull request #268 from actions/dependabot/npm_and_yarn/eslint-config-pr...
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/deploy-pages&package-manager=github_actions&previous-version=2&new-version=4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) You can trigger a rebase of this PR by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
> **Note** > Automatic rebases have been disabled on this pull request as it has been open for over 30 days. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> --- .github/workflows/publish-module-index.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-module-index.yml b/.github/workflows/publish-module-index.yml index 3d3523adc5..a494876071 100644 --- a/.github/workflows/publish-module-index.yml +++ b/.github/workflows/publish-module-index.yml @@ -115,4 +115,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v2 + uses: actions/deploy-pages@v4 From 7ff764c47f71020f51194856f48f41dfa6c93eb3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 10:28:45 +0000 Subject: [PATCH 22/73] fix: bump actions/configure-pages from 3 to 4 (#704) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/configure-pages](https://github.com/actions/configure-pages) from 3 to 4.
Release notes

Sourced from actions/configure-pages's releases.

v4.0.0

Changelog

See details of all code changes since previous release.

v3.0.7

Changelog

See details of all code changes since previous release.

v3.0.6

Changelog

See details of all code changes since previous release.

v3.0.5

Changelog

See details of all code changes since previous release.

v3.0.4

Changelog

... (truncated)

Commits
  • 1f0c5cd Merge pull request #117 from actions/use-node-version-file
  • 591bb0d Merge branch 'main' into use-node-version-file
  • 1465f01 Merge pull request #108 from takost/update-to-node-20
  • f2fc553 Merge branch 'main' into update-to-node-20
  • 373694e Use a centralized .node-version file
  • 3a01413 Update action to node20
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/configure-pages&package-manager=github_actions&previous-version=3&new-version=4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) You can trigger a rebase of this PR by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
> **Note** > Automatic rebases have been disabled on this pull request as it has been open for over 30 days. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> --- .github/workflows/publish-module-index.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-module-index.yml b/.github/workflows/publish-module-index.yml index a494876071..bc247b2afb 100644 --- a/.github/workflows/publish-module-index.yml +++ b/.github/workflows/publish-module-index.yml @@ -93,7 +93,7 @@ jobs: - name: Setup Pages id: pages - uses: actions/configure-pages@v3 + uses: actions/configure-pages@v4 - name: Build with Jekyll working-directory: ./docs/jekyll From f592be285defb31de2307ee52f5986a3ae8c2ddf Mon Sep 17 00:00:00 2001 From: Kris Baranek Date: Thu, 14 Mar 2024 11:49:04 +0100 Subject: [PATCH 23/73] feat: added `eventHubResourceIds` output to the EventHub Namespace module (#1252) ## Description Added a new output `eventHubResourceIds` to the EventHub Namespace module. ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.event-hub.namespace](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.event-hub.namespace.yml/badge.svg?branch=users%2Fkrbar%2FeventHubOutput)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.event-hub.namespace.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [x] Azure Verified Module updates: - [ ] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [x] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [x] I have run `Set-AVMModule` locally to generate the supporting module files. - [x] My corresponding pipelines / checks run clean and green without any errors or warnings --- avm/res/event-hub/namespace/README.md | 1 + avm/res/event-hub/namespace/main.bicep | 4 +++- avm/res/event-hub/namespace/main.json | 12 +++++++++++- avm/res/event-hub/namespace/version.json | 2 +- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/avm/res/event-hub/namespace/README.md b/avm/res/event-hub/namespace/README.md index 984140f5c2..d776735da8 100644 --- a/avm/res/event-hub/namespace/README.md +++ b/avm/res/event-hub/namespace/README.md @@ -1815,6 +1815,7 @@ Switch to make the Event Hub Namespace zone redundant. | Output | Type | Description | | :-- | :-- | :-- | +| `eventHubResourceIds` | array | The Resources IDs of the EventHubs within this eventspace. | | `location` | string | The location the resource was deployed into. | | `name` | string | The name of the eventspace. | | `resourceGroupName` | string | The resource group where the namespace is deployed. | diff --git a/avm/res/event-hub/namespace/main.bicep b/avm/res/event-hub/namespace/main.bicep index 86527fcf2c..ace3641cec 100644 --- a/avm/res/event-hub/namespace/main.bicep +++ b/avm/res/event-hub/namespace/main.bicep @@ -156,7 +156,6 @@ resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableT } } - resource eventHubNamespace 'Microsoft.EventHub/namespaces@2022-10-01-preview' = { name: name location: location @@ -361,6 +360,9 @@ output systemAssignedMIPrincipalId string = eventHubNamespace.?identity.?princip @description('The location the resource was deployed into.') output location string = eventHubNamespace.location +@description('The Resources IDs of the EventHubs within this eventspace.') +output eventHubResourceIds array = [for index in range(0, length(eventhubs ?? [])): eventHubNamespace_eventhubs[index].outputs.resourceId] + // =============== // // Definitions // // =============== // diff --git a/avm/res/event-hub/namespace/main.json b/avm/res/event-hub/namespace/main.json index 7b4d5d960f..fa65131a62 100644 --- a/avm/res/event-hub/namespace/main.json +++ b/avm/res/event-hub/namespace/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "2606348480823352941" + "templateHash": "11007166139796021582" }, "name": "Event Hub Namespaces", "description": "This module deploys an Event Hub Namespace.", @@ -2535,6 +2535,16 @@ "description": "The location the resource was deployed into." }, "value": "[reference('eventHubNamespace', '2022-10-01-preview', 'full').location]" + }, + "eventHubResourceIds": { + "type": "array", + "metadata": { + "description": "The Resources IDs of the EventHubs within this eventspace." + }, + "copy": { + "count": "[length(range(0, length(coalesce(parameters('eventhubs'), createArray()))))]", + "input": "[reference(format('eventHubNamespace_eventhubs[{0}]', range(0, length(coalesce(parameters('eventhubs'), createArray())))[copyIndex()])).outputs.resourceId.value]" + } } } } \ No newline at end of file diff --git a/avm/res/event-hub/namespace/version.json b/avm/res/event-hub/namespace/version.json index 83083db694..1c035df49f 100644 --- a/avm/res/event-hub/namespace/version.json +++ b/avm/res/event-hub/namespace/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" ] From 58b3eca532c6ba9d9c36f865759291d959c896ba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 10:50:14 +0000 Subject: [PATCH 24/73] fix: bump actions/setup-dotnet from 3 to 4 (#702) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 3 to 4.
Release notes

Sourced from actions/setup-dotnet's releases.

v4.0.0

What's Changed

In the scope of this release, the version of the Node.js runtime was updated to 20. The majority of dependencies were updated to the latest versions. From now on, the code for the setup-dotnet will run on Node.js 20 instead of Node.js 16.

Breaking changes

Update Node.js runtime to version 20 by @​harithavattikuti in #484

Non-breaking changes

New Contributors

Full Changelog: https://github.com/actions/setup-dotnet/compare/v3...v4.0.0

v3.2.0

What's Changed

In scope of this minor release, the ability to cache the NuGet global-packages folder was added in actions/setup-dotnet#303 by @​nogic1008

For caching, the action uses the @​toolkit/cache library under the hood, which in turn allows getting rid of configuring the @​actions/cache action separately.

Such input parameters as cache and cache-dependency-path were added. The cache input is optional, and caching is turned off by default, cache-dependency-path is used to specify the path to a dependency file - packages.lock.json.

Example of use-case:

- uses: actions/setup-dotnet@v3
  with:
    dotnet-version: 6.x
    cache: true
    cache-dependency-path: subdir/packages.lock.json

More details can be found in the action's documentation.

Full Changelog: https://github.com/actions/setup-dotnet/compare/v3...v3.2.0

v3.1.0

What's Changed

This minor release includes the following new features:

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-dotnet&package-manager=github_actions&previous-version=3&new-version=4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) You can trigger a rebase of this PR by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
> **Note** > Automatic rebases have been disabled on this pull request as it has been open for over 30 days. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> --- .github/workflows/on-pull-request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/on-pull-request.yml b/.github/workflows/on-pull-request.yml index 2745ead0e1..588b11f8ea 100644 --- a/.github/workflows/on-pull-request.yml +++ b/.github/workflows/on-pull-request.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@v4 - name: Setup .NET - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: 7.0.x From 49fd5b8a09595429555ef28ec6853536d177cb58 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 10:51:32 +0000 Subject: [PATCH 25/73] chore(deps-dev): bump axios from 0.27.2 to 0.28.0 (#1259) Bumps [axios](https://github.com/axios/axios) from 0.27.2 to 0.28.0.
Release notes

Sourced from axios's releases.

Release v0.28.0

Release notes:

Bug Fixes

  • fix(security): fixed CVE-2023-45857 by backporting withXSRFToken option to v0.x (#6091)

Backports from v1.x:

  • Allow null indexes on formSerializer and paramsSerializer v0.x (#4961)
  • Fixing content-type header repeated #4745
  • Fixed timeout error message for HTTP 4738
  • Added axios.formToJSON method (#4735)
  • URL params serializer (#4734)
  • Fixed toFormData Blob issue on node>v17 #4728
  • Adding types for progress event callbacks #4675
  • Fixed max body length defaults #4731
  • Added data URL support for node.js (#4725)
  • Added isCancel type assert (#4293)
  • Added the ability for the url-encoded-form serializer to respect the formSerializer config (#4721)
  • Add string[] to AxiosRequestHeaders type (#4322)
  • Allow type definition for axios instance methods (#4224)
  • Fixed AxiosError stack capturing; (#4718)
  • Fixed AxiosError status code type; (#4717)
  • Adding Canceler parameters config and request (#4711)
  • fix(types): allow to specify partial default headers for instance creation (#4185)
  • Added blob to the list of protocols supported by the browser (#4678)
  • Fixing Z_BUF_ERROR when no content (#4701)
  • Fixed race condition on immediate requests cancellation (#4261)
  • Added a clear() function to the request and response interceptors object so a user can ensure that all interceptors have been removed from an Axios instance axios/axios#4248
  • Added generic AxiosAbortSignal TS interface to avoid importing AbortController polyfill (#4229)
  • Fix TS definition for AxiosRequestTransformer (#4201)
  • Use type alias instead of interface for AxiosPromise (#4505)
  • Include request and config when creating a CanceledError instance (#4659)
  • Added generic TS types for the exposed toFormData helper (#4668)
  • Optimized the code that checks cancellation (#4587)
  • Replaced webpack with rollup (#4596)
  • Added stack trace to AxiosError (#4624)
  • Updated AxiosError.config to be optional in the type definition (#4665)
  • Removed incorrect argument for NetworkError constructor (#4656)
Changelog

Sourced from axios's changelog.

0.28.0 (2024-02-12)

Release notes:

Bug Fixes

  • fix(security): fixed CVE-2023-45857 by backporting withXSRFToken option to v0.x (#6091)

Backports from v1.x:

  • Allow null indexes on formSerializer and paramsSerializer v0.x (#4961)
  • Fixing content-type header repeated #4745
  • Fixed timeout error message for HTTP 4738
  • Added axios.formToJSON method (#4735)
  • URL params serializer (#4734)
  • Fixed toFormData Blob issue on node>v17 #4728
  • Adding types for progress event callbacks #4675
  • Fixed max body length defaults #4731
  • Added data URL support for node.js (#4725)
  • Added isCancel type assert (#4293)
  • Added the ability for the url-encoded-form serializer to respect the formSerializer config (#4721)
  • Add string[] to AxiosRequestHeaders type (#4322)
  • Allow type definition for axios instance methods (#4224)
  • Fixed AxiosError stack capturing; (#4718)
  • Fixed AxiosError status code type; (#4717)
  • Adding Canceler parameters config and request (#4711)
  • fix(types): allow to specify partial default headers for instance creation (#4185)
  • Added blob to the list of protocols supported by the browser (#4678)
  • Fixing Z_BUF_ERROR when no content (#4701)
  • Fixed race condition on immediate requests cancellation (#4261)
  • Added a clear() function to the request and response interceptors object so a user can ensure that all interceptors have been removed from an Axios instance axios/axios#4248
  • Added generic AxiosAbortSignal TS interface to avoid importing AbortController polyfill (#4229)
  • Fix TS definition for AxiosRequestTransformer (#4201)
  • Use type alias instead of interface for AxiosPromise (#4505)
  • Include request and config when creating a CanceledError instance (#4659)
  • Added generic TS types for the exposed toFormData helper (#4668)
  • Optimized the code that checks cancellation (#4587)
  • Replaced webpack with rollup (#4596)
  • Added stack trace to AxiosError (#4624)
  • Updated AxiosError.config to be optional in the type definition (#4665)
  • Removed incorrect argument for NetworkError constructor (#4656)
Commits
  • 3b7635a [Release] v0.28.0 (#6211)
  • 27c0076 feat(backport): added ability for paramsSerializer to handle function; (#6227)
  • 80c3d74 chore(ci): backported publish action; (#6224)
  • 2755df5 fix(security): fixed CVE-2023-45857 by backporting withXSRFToken option to ...
  • 880b42e docs: Fix a typo in README
  • c4bf0a4 Allow null indexes on formSerializer and paramsSerializer v0.x (#4961)
  • 1e2679f fix: [Types] Type of header in AxiosRequestConfig / for Axios.create is incor...
  • 80b546c fix: loosing request header (#4858) (#4871)
  • 6acb5ef feat: brower platform add data protocol. (#4814)
  • bbb2264 fix(typing): axios response headers can be undefined (#4813)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=axios&package-manager=npm_and_yarn&previous-version=0.27.2&new-version=0.28.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/Azure/bicep-registry-modules/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> --- package-lock.json | 36 +++++++++++++++++++++++++----------- package.json | 2 +- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index a89764c251..cd483773f3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "devDependencies": { "@actions/core": "^1.9.1", "@actions/github": "^5.0.0", - "axios": "^0.27.2", + "axios": "^0.28.0", "eslint": "^8.9.0", "eslint-config-prettier": "^8.3.0", "markdown-table": "^3.0.2", @@ -293,13 +293,14 @@ "dev": true }, "node_modules/axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.28.0.tgz", + "integrity": "sha512-Tu7NYoGY4Yoc7I+Npf9HhUMtEEpV7ZiLH9yndTCoNhcpBH0kwcvFbzYN9/u5QKI5A6uefjsNNWaz5olJVYS62Q==", "dev": true, "dependencies": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, "node_modules/balanced-match": { @@ -1077,6 +1078,12 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -1565,13 +1572,14 @@ "dev": true }, "axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.28.0.tgz", + "integrity": "sha512-Tu7NYoGY4Yoc7I+Npf9HhUMtEEpV7ZiLH9yndTCoNhcpBH0kwcvFbzYN9/u5QKI5A6uefjsNNWaz5olJVYS62Q==", "dev": true, "requires": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, "balanced-match": { @@ -2147,6 +2155,12 @@ "integrity": "sha512-mtuzdiBbHwPEgl7NxWlqOkithPyp4VN93V7VeHVWBF+ad3I5avc0RVDT4oImXQy9H/AqxA2NSQH8pSxHW6FYbQ==", "dev": true }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", diff --git a/package.json b/package.json index 911852e08f..a5b450c286 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "devDependencies": { "@actions/core": "^1.9.1", "@actions/github": "^5.0.0", - "axios": "^0.27.2", + "axios": "^0.28.0", "eslint": "^8.9.0", "eslint-config-prettier": "^8.3.0", "markdown-table": "^3.0.2", From 8dacd09e5d0d6e7303356920410a8aa0bbacdb42 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 15:28:16 +0000 Subject: [PATCH 26/73] fix: bump mathieudutour/github-tag-action from 6.1 to 6.2 (#1284) Bumps [mathieudutour/github-tag-action](https://github.com/mathieudutour/github-tag-action) from 6.1 to 6.2.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=mathieudutour/github-tag-action&package-manager=github_actions&previous-version=6.1&new-version=6.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/fork-on-push-brm-generate.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/fork-on-push-brm-generate.yml b/.github/workflows/fork-on-push-brm-generate.yml index b24a15c3fa..06a832098c 100644 --- a/.github/workflows/fork-on-push-brm-generate.yml +++ b/.github/workflows/fork-on-push-brm-generate.yml @@ -52,7 +52,7 @@ jobs: - name: Bump version and push tag id: tag_version - uses: mathieudutour/github-tag-action@v6.1 + uses: mathieudutour/github-tag-action@v6.2 with: github_token: ${{ secrets.GITHUB_TOKEN }} tag_prefix: "${{ steps.branch.outputs._1 }}/${{ steps.branch.outputs._2 }}/" From fe467e7604a0305df7fd059bc9c5962b918cd10c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 15:29:39 +0000 Subject: [PATCH 27/73] fix: bump azure/CLI from 1 to 2 (#1282) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [azure/CLI](https://github.com/azure/cli) from 1 to 2.
Release notes

Sourced from azure/CLI's releases.

GitHub Action for Azure CLI v2

What's Changed

New Contributors

Full Changelog: https://github.com/Azure/cli/compare/v1.0.9...v2

GitHub Action for Azure CLI v1.0.9

  • Set action failure on a non-Linux-based OS (#123)

GitHub Action for Azure CLI v1.0.8

  • Fix #103: Dealing with un-escaped environment variables which cause escalation of privilege (#105)

GitHub Action for Azure CLI v1.0.7

  • Upgraded action to use node 16 instead of node 12
  • Upgrade @​actions/core to ^1.10.0
  • Resolved other minor issues like Azure/cli#87 and Azure/cli#84

GitHub Action for Azure CLI v1.0.6

Resolved customer issue: Error: /bin/sh: 1: az: not found in v1.0.5 Azure/cli#62

GitHub Action for Azure CLI v1.0.5

Resolved compatibility issues between az cli version on agent and container.

cli@v1.0.4

  1. Adding support for using env. variables via GITHUB_ENV
  2. Security vulnerability fix

GitHub Action for Azure CLI v1.0.3

User-defined environment variables present in the workflow are now accessible while execution of Azure CLI script.

GitHub Action for Azure CLI v1.0.2

Default environment variables provided by GitHub are now accessible while execution of Azure CLI script. Environment variables with prefix GITHUB_* are accessible during the script execution.

GitHub Action for Azure CLI v1.0.1

GITHUB_SHA default environment variable is available to use in the script.

Changelog

Sourced from azure/CLI's changelog.

Releasing a new version

Semanting versioning is used to release different versions of the action. Following steps are to be followed :

  1. Create a new branch for every major version.
    Example, releases/v1, releases/v2.
  2. For every minor and patch release for a major version, update the corresponding release branch.
    Example, for releasing v1.1.1, update releases/v1.
  3. Create tags for every new release (major/minor/patch).
    Example,v1.0.0. , v1.0.1, v2.0.1, etc. and also have tags like v1, v2 for every major version release.
  4. On releasing minor and patch versions, update the tag of the corresponding major version.
    Example, for releasing v1.0.1, update the v1 tag to point to the ref of the current release.
    The following commands are to be run on the release\v1 branch so that it picks the latest commit and updates the v1 tag accordingly : (Ensure that you are on same commit locally as you want to release)
  • git tag -fa v1 -m "Update v1 tag"
  • git push origin v1 --force
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=azure/CLI&package-manager=github_actions&previous-version=1&new-version=2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish-module-index.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-module-index.yml b/.github/workflows/publish-module-index.yml index bc247b2afb..e92af3cdc2 100644 --- a/.github/workflows/publish-module-index.yml +++ b/.github/workflows/publish-module-index.yml @@ -50,7 +50,7 @@ jobs: subscription-id: ${{ secrets.PUBLISH_SUBSCRIPTION_ID }} - name: Upload to blob storage - uses: azure/CLI@v1 + uses: azure/CLI@v2 with: inlineScript: | az storage blob upload --account-name biceplivedatasaprod --container-name bicep-cdn-live-data-container --name module-index --file moduleIndex.json --auth-mode login --overwrite From ab04eebdb168ad67205aa88d1db5064b14b23044 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 15:30:15 +0000 Subject: [PATCH 28/73] fix: bump actions/upload-artifact from 3 to 4 (#1281) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4.
Release notes

Sourced from actions/upload-artifact's releases.

v4.0.0

What's Changed

The release of upload-artifact@v4 and download-artifact@v4 are major changes to the backend architecture of Artifacts. They have numerous performance and behavioral improvements.

ℹ️ However, this is a major update that includes breaking changes. Artifacts created with versions v3 and below are not compatible with the v4 actions. Uploads and downloads must use the same major actions versions. There are also key differences from previous versions that may require updates to your workflows.

For more information, please see:

  1. The changelog post.
  2. The README.
  3. The migration documentation.
  4. As well as the underlying npm package, @​actions/artifact documentation.

New Contributors

Full Changelog: https://github.com/actions/upload-artifact/compare/v3...v4.0.0

v3.1.3

What's Changed

Full Changelog: https://github.com/actions/upload-artifact/compare/v3...v3.1.3

v3.1.2

  • Update all @actions/* NPM packages to their latest versions- #374
  • Update all dev dependencies to their most recent versions - #375

v3.1.1

  • Update actions/core package to latest version to remove set-output deprecation warning #351

v3.1.0

What's Changed

Commits
  • 5d5d22a Merge pull request #515 from actions/eggyhead/update-artifact-v2.1.1
  • f1e993d update artifact license
  • 4881bfd updating dist:
  • a30777e @​eggyhead
  • 3a80482 Merge pull request #511 from actions/robherley/migration-docs-typo
  • 9d63e3f Merge branch 'main' into robherley/migration-docs-typo
  • dfa1ab2 fix typo with v3 artifact downloads in migration guide
  • d00351b Merge pull request #509 from markmssd/patch-1
  • 707f5a7 Update limitation of 10 artifacts upload to 500
  • 26f96df Merge pull request #505 from actions/robherley/merge-artifacts
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/upload-artifact&package-manager=github_actions&previous-version=3&new-version=4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish-module-index.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish-module-index.yml b/.github/workflows/publish-module-index.yml index e92af3cdc2..edb50ffb54 100644 --- a/.github/workflows/publish-module-index.yml +++ b/.github/workflows/publish-module-index.yml @@ -37,7 +37,7 @@ jobs: await script({ require, github, context, core }) - name: Upload artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: moduleIndex.json path: moduleIndex.json @@ -78,7 +78,7 @@ jobs: await script({ require, github, context, core }) - name: Upload Markdown artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: path: ./docs/jekyll/index.md name: index.md From de266f69615192c2d4db1c56b9f5cc63a624a0e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 15:31:24 +0000 Subject: [PATCH 29/73] fix: bump actions/download-artifact from 3 to 4 (#1283) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 3 to 4.
Release notes

Sourced from actions/download-artifact's releases.

v4.0.0

What's Changed

The release of upload-artifact@v4 and download-artifact@v4 are major changes to the backend architecture of Artifacts. They have numerous performance and behavioral improvements.

ℹ️ However, this is a major update that includes breaking changes. Artifacts created with versions v3 and below are not compatible with the v4 actions. Uploads and downloads must use the same major actions versions. There are also key differences from previous versions that may require updates to your workflows.

For more information, please see:

  1. The changelog post.
  2. The README.
  3. The migration documentation.
  4. As well as the underlying npm package, @​actions/artifact documentation.

New Contributors

Full Changelog: https://github.com/actions/download-artifact/compare/v3...v4.0.0

v3.0.2

  • Bump @actions/artifact to v1.1.1 - actions/download-artifact#195
  • Fixed a bug in Node16 where if an HTTP download finished too quickly (<1ms, e.g. when it's mocked) we attempt to delete a temp file that has not been created yet actions/toolkit#1278

v3.0.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/download-artifact&package-manager=github_actions&previous-version=3&new-version=4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> --- .github/workflows/publish-module-index.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-module-index.yml b/.github/workflows/publish-module-index.yml index edb50ffb54..885451f81b 100644 --- a/.github/workflows/publish-module-index.yml +++ b/.github/workflows/publish-module-index.yml @@ -66,7 +66,7 @@ jobs: run: npm ci - name: Download artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: moduleIndex.json From e142695f06ac11ee4bdca66b08474a5f4de80887 Mon Sep 17 00:00:00 2001 From: Alexander Sehr Date: Thu, 14 Mar 2024 11:33:17 -0400 Subject: [PATCH 30/73] fix: Fixed API version reference in SSH Key module (#1243) ## Description Fixed API version reference in SSH Key module ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.compute.ssh-public-key](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.compute.ssh-public-key.yml/badge.svg?branch=users%2Falsehr%2FsshReadMeFix&event=workflow_dispatch)](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.compute.ssh-public-key.yml) | --- avm/res/compute/ssh-public-key/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avm/res/compute/ssh-public-key/README.md b/avm/res/compute/ssh-public-key/README.md index c3305cfed5..ec1cf6c06c 100644 --- a/avm/res/compute/ssh-public-key/README.md +++ b/avm/res/compute/ssh-public-key/README.md @@ -19,7 +19,7 @@ This module deploys a Public SSH Key. | :-- | :-- | | `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.Compute/sshPublicKeys` | [2023-07-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Compute/sshPublicKeys) | +| `Microsoft.Compute/sshPublicKeys` | [2023-07-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Compute/2023-07-01/sshPublicKeys) | ## Usage examples From d264ab0edec18b01713268a891bc7cf4cc661565 Mon Sep 17 00:00:00 2001 From: Kris Baranek Date: Thu, 14 Mar 2024 16:36:22 +0100 Subject: [PATCH 31/73] feat: New Module `avm/res/event-grid/namespace` (#1208) ## Description New development - module `avm/res/event-grid/namespace`. ## Adding a new module - [x] A proposal has been submitted and approved. - [ ] I have included "Closes #{module_proposal_issue_number}" in the PR description. - [ ] I have run `brm validate` locally to verify the module files. - [x] I have run deployment tests locally to ensure the module is deployable. ## Pipeline references | Pipeline | | - | | [![avm.res.event-grid.namespace](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.event-grid.namespace.yml/badge.svg?branch=users%2Fkrbar%2FeventGridModule)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.event-grid.namespace.yml) | --- .github/CODEOWNERS | 1 + .github/ISSUE_TEMPLATE/avm_module_issue.yml | 1 + .../avm.res.event-grid.namespace.yml | 85 + avm/res/event-grid/namespace/README.md | 2187 +++++++++++++ .../namespace/ca-certificate/README.md | 83 + .../namespace/ca-certificate/main.bicep | 52 + .../namespace/ca-certificate/main.json | 85 + .../namespace/client-group/README.md | 83 + .../namespace/client-group/main.bicep | 52 + .../namespace/client-group/main.json | 85 + avm/res/event-grid/namespace/client/README.md | 128 + .../event-grid/namespace/client/main.bicep | 81 + avm/res/event-grid/namespace/client/main.json | 133 + avm/res/event-grid/namespace/main.bicep | 510 +++ avm/res/event-grid/namespace/main.json | 2825 +++++++++++++++++ .../namespace/permission-binding/README.md | 106 + .../namespace/permission-binding/main.bicep | 64 + .../namespace/permission-binding/main.json | 103 + .../tests/e2e/defaults/main.test.bicep | 46 + .../tests/e2e/max/dependencies.bicep | 102 + .../namespace/tests/e2e/max/main.test.bicep | 244 ++ .../tests/e2e/mqttct/dependencies.bicep | 41 + .../tests/e2e/mqttct/main.test.bicep | 194 ++ .../tests/e2e/mqttnt/dependencies.bicep | 37 + .../tests/e2e/mqttnt/main.test.bicep | 195 ++ .../tests/e2e/waf-aligned/dependencies.bicep | 63 + .../tests/e2e/waf-aligned/main.test.bicep | 119 + .../namespace/topic-space/README.md | 174 + .../namespace/topic-space/main.bicep | 106 + .../namespace/topic-space/main.json | 199 ++ avm/res/event-grid/namespace/topic/README.md | 232 ++ .../topic/event-subscription/README.md | 191 ++ .../topic/event-subscription/main.bicep | 118 + .../topic/event-subscription/main.json | 222 ++ avm/res/event-grid/namespace/topic/main.bicep | 147 + avm/res/event-grid/namespace/topic/main.json | 525 +++ avm/res/event-grid/namespace/version.json | 7 + 37 files changed, 9626 insertions(+) create mode 100644 .github/workflows/avm.res.event-grid.namespace.yml create mode 100644 avm/res/event-grid/namespace/README.md create mode 100644 avm/res/event-grid/namespace/ca-certificate/README.md create mode 100644 avm/res/event-grid/namespace/ca-certificate/main.bicep create mode 100644 avm/res/event-grid/namespace/ca-certificate/main.json create mode 100644 avm/res/event-grid/namespace/client-group/README.md create mode 100644 avm/res/event-grid/namespace/client-group/main.bicep create mode 100644 avm/res/event-grid/namespace/client-group/main.json create mode 100644 avm/res/event-grid/namespace/client/README.md create mode 100644 avm/res/event-grid/namespace/client/main.bicep create mode 100644 avm/res/event-grid/namespace/client/main.json create mode 100644 avm/res/event-grid/namespace/main.bicep create mode 100644 avm/res/event-grid/namespace/main.json create mode 100644 avm/res/event-grid/namespace/permission-binding/README.md create mode 100644 avm/res/event-grid/namespace/permission-binding/main.bicep create mode 100644 avm/res/event-grid/namespace/permission-binding/main.json create mode 100644 avm/res/event-grid/namespace/tests/e2e/defaults/main.test.bicep create mode 100644 avm/res/event-grid/namespace/tests/e2e/max/dependencies.bicep create mode 100644 avm/res/event-grid/namespace/tests/e2e/max/main.test.bicep create mode 100644 avm/res/event-grid/namespace/tests/e2e/mqttct/dependencies.bicep create mode 100644 avm/res/event-grid/namespace/tests/e2e/mqttct/main.test.bicep create mode 100644 avm/res/event-grid/namespace/tests/e2e/mqttnt/dependencies.bicep create mode 100644 avm/res/event-grid/namespace/tests/e2e/mqttnt/main.test.bicep create mode 100644 avm/res/event-grid/namespace/tests/e2e/waf-aligned/dependencies.bicep create mode 100644 avm/res/event-grid/namespace/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/res/event-grid/namespace/topic-space/README.md create mode 100644 avm/res/event-grid/namespace/topic-space/main.bicep create mode 100644 avm/res/event-grid/namespace/topic-space/main.json create mode 100644 avm/res/event-grid/namespace/topic/README.md create mode 100644 avm/res/event-grid/namespace/topic/event-subscription/README.md create mode 100644 avm/res/event-grid/namespace/topic/event-subscription/main.bicep create mode 100644 avm/res/event-grid/namespace/topic/event-subscription/main.json create mode 100644 avm/res/event-grid/namespace/topic/main.bicep create mode 100644 avm/res/event-grid/namespace/topic/main.json create mode 100644 avm/res/event-grid/namespace/version.json diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 19091cd52b..99557d99bb 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -49,6 +49,7 @@ #/avm/res/digital-twins/digital-twins-instance/ @Azure/avm-res-digitaltwins-digitaltwinsinstance-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/document-db/database-account/ @Azure/avm-res-documentdb-databaseaccount-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/event-grid/domain/ @Azure/avm-res-eventgrid-domain-module-owners-bicep @Azure/avm-core-team-technical-bicep +/avm/res/event-grid/namespace/ @Azure/avm-res-eventgrid-namespace-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/event-grid/system-topic/ @Azure/avm-res-eventgrid-systemtopic-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/event-grid/topic/ @Azure/avm-res-eventgrid-topic-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/event-hub/namespace/ @Azure/avm-res-eventhub-namespace-module-owners-bicep @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 39a45a8751..69b3fd5b21 100644 --- a/.github/ISSUE_TEMPLATE/avm_module_issue.yml +++ b/.github/ISSUE_TEMPLATE/avm_module_issue.yml @@ -83,6 +83,7 @@ body: # - "avm/res/digital-twins/digital-twins-instance" - "avm/res/document-db/database-account" - "avm/res/event-grid/domain" + - "avm/res/event-grid/namespace" - "avm/res/event-grid/system-topic" - "avm/res/event-grid/topic" - "avm/res/event-hub/namespace" diff --git a/.github/workflows/avm.res.event-grid.namespace.yml b/.github/workflows/avm.res.event-grid.namespace.yml new file mode 100644 index 0000000000..59046c0cc4 --- /dev/null +++ b/.github/workflows/avm.res.event-grid.namespace.yml @@ -0,0 +1,85 @@ +name: "avm.res.event-grid.namespace" + +on: + schedule: + - cron: "0 12 1/15 * *" # Bi-Weekly Test (on 1st & 15th of month) + 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 + push: + branches: + - main + paths: + - ".github/actions/templates/avm-**" + - ".github/workflows/avm.template.module.yml" + - ".github/workflows/avm.res.event-grid.namespace.yml" + - "avm/res/event-grid/namespace/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/event-grid/namespace" + workflowPath: ".github/workflows/avm.res.event-grid.namespace.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-latest + name: "Initialize pipeline" + steps: + - name: "Checkout" + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: "Set input parameters to output variables" + id: get-workflow-param + uses: ./.github/actions/templates/avm-getWorkflowInput + with: + workflowPath: "${{ env.workflowPath}}" + - name: "Get module test file paths" + id: get-module-test-file-paths + uses: ./.github/actions/templates/avm-getModuleTestFiles + with: + modulePath: "${{ env.modulePath }}" + outputs: + workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }} + moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} + psRuleModuleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.psRuleModuleTestFilePaths }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Run" + permissions: + id-token: write # For OIDC + contents: write # For release tags + needs: + - job_initialize_pipeline + uses: ./.github/workflows/avm.template.module.yml + with: + workflowInput: "${{ needs.job_initialize_pipeline.outputs.workflowInput }}" + moduleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.moduleTestFilePaths }}" + psRuleModuleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.psRuleModuleTestFilePaths }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit diff --git a/avm/res/event-grid/namespace/README.md b/avm/res/event-grid/namespace/README.md new file mode 100644 index 0000000000..62df5825ff --- /dev/null +++ b/avm/res/event-grid/namespace/README.md @@ -0,0 +1,2187 @@ +# Event Grid Namespaces `[Microsoft.EventGrid/namespaces]` + +This module deploys an Event Grid Namespace. + +## Navigation + +- [Resource Types](#Resource-Types) +- [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` | [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.EventGrid/namespaces` | [2023-12-15-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.EventGrid/2023-12-15-preview/namespaces) | +| `Microsoft.EventGrid/namespaces/caCertificates` | [2023-12-15-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.EventGrid/2023-12-15-preview/namespaces/caCertificates) | +| `Microsoft.EventGrid/namespaces/clientGroups` | [2023-12-15-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.EventGrid/2023-12-15-preview/namespaces/clientGroups) | +| `Microsoft.EventGrid/namespaces/clients` | [2023-12-15-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.EventGrid/2023-12-15-preview/namespaces/clients) | +| `Microsoft.EventGrid/namespaces/permissionBindings` | [2023-12-15-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.EventGrid/2023-12-15-preview/namespaces/permissionBindings) | +| `Microsoft.EventGrid/namespaces/topics` | [2023-12-15-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.EventGrid/2023-12-15-preview/namespaces/topics) | +| `Microsoft.EventGrid/namespaces/topics/eventSubscriptions` | [2023-12-15-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.EventGrid/2023-12-15-preview/namespaces/topics/eventSubscriptions) | +| `Microsoft.EventGrid/namespaces/topicSpaces` | [2023-12-15-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.EventGrid/2023-12-15-preview/namespaces/topicSpaces) | +| `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) | + +## 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/res/event-grid/namespace:`. + +- [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) +- [WAF-aligned](#example-5-waf-aligned) + +### Example 1: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. + + +
+ +via Bicep module + +```bicep +module namespace 'br/public:avm/res/event-grid/namespace:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-egnmin' + params: { + // Required parameters + name: 'egnmin001' + // Non-required parameters + location: '' + } +} +``` + +
+

+ +

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

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

+ +via Bicep module + +```bicep +module namespace 'br/public:avm/res/event-grid/namespace:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-egnmax' + params: { + // Required parameters + name: 'egnmax001' + // Non-required parameters + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + '' + ] + } + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + '' + ] + subnetResourceId: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + { + privateDnsZoneResourceIds: [ + '' + ] + subnetResourceId: '' + } + ] + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + topics: [ + { + eventRetentionInDays: 7 + eventSubscriptions: [ + { + deliveryConfiguration: { + deliveryMode: 'Queue' + queue: { + eventTimeToLive: 'P7D' + maxDeliveryCount: 10 + receiveLockDurationInSeconds: 60 + } + } + name: 'subscription1' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + } + { + deliveryConfiguration: { + deliveryMode: 'Push' + push: { + deliveryWithResourceIdentity: { + destination: { + endpointType: 'EventHub' + properties: { + deliveryAttributeMappings: [ + { + name: 'StaticHeader1' + properties: { + isSecret: false + value: 'staticVaule' + } + type: 'Static' + } + { + name: 'DynamicHeader1' + properties: { + sourceField: 'id' + } + type: 'Dynamic' + } + { + name: 'StaticSecretHeader1' + properties: { + isSecret: true + value: 'Hidden' + } + type: 'Static' + } + ] + resourceId: '' + } + } + identity: { + type: 'UserAssigned' + userAssignedIdentity: '' + } + } + eventTimeToLive: 'P7D' + maxDeliveryCount: 10 + } + } + name: 'subscription2' + } + ] + name: 'topic1' + } + { + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + name: 'topic2' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + } + ] + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "egnmax001" + }, + // Non-required parameters + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "managedIdentities": { + "value": { + "systemAssigned": true, + "userAssignedResourceIds": [ + "" + ] + } + }, + "privateEndpoints": { + "value": [ + { + "privateDnsZoneResourceIds": [ + "" + ], + "subnetResourceId": "", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + { + "privateDnsZoneResourceIds": [ + "" + ], + "subnetResourceId": "" + } + ] + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + "topics": { + "value": [ + { + "eventRetentionInDays": 7, + "eventSubscriptions": [ + { + "deliveryConfiguration": { + "deliveryMode": "Queue", + "queue": { + "eventTimeToLive": "P7D", + "maxDeliveryCount": 10, + "receiveLockDurationInSeconds": 60 + } + }, + "name": "subscription1", + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + { + "deliveryConfiguration": { + "deliveryMode": "Push", + "push": { + "deliveryWithResourceIdentity": { + "destination": { + "endpointType": "EventHub", + "properties": { + "deliveryAttributeMappings": [ + { + "name": "StaticHeader1", + "properties": { + "isSecret": false, + "value": "staticVaule" + }, + "type": "Static" + }, + { + "name": "DynamicHeader1", + "properties": { + "sourceField": "id" + }, + "type": "Dynamic" + }, + { + "name": "StaticSecretHeader1", + "properties": { + "isSecret": true, + "value": "Hidden" + }, + "type": "Static" + } + ], + "resourceId": "" + } + }, + "identity": { + "type": "UserAssigned", + "userAssignedIdentity": "" + } + }, + "eventTimeToLive": "P7D", + "maxDeliveryCount": 10 + } + }, + "name": "subscription2" + } + ], + "name": "topic1" + }, + { + "lock": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + }, + "name": "topic2", + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + } + ] + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module namespace 'br/public:avm/res/event-grid/namespace:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-egnmqttct' + params: { + // Required parameters + name: 'egnmqttct001' + // Non-required parameters + alternativeAuthenticationNameSources: [ + 'ClientCertificateEmail' + 'ClientCertificateUri' + ] + clientGroups: [ + { + description: 'this is group1' + name: 'group1' + query: 'attributes.keyName IN [\'a\', \'b\', \'c\']' + } + ] + clients: [ + { + attributes: { + deviceTypes: [ + 'Fan' + 'Light' + ] + floor: 12 + room: '345' + } + authenticationName: 'client2auth' + clientCertificateAuthenticationAllowedThumbprints: [ + '1111111111111111111111111111111111111111' + '2222222222222222222222222222222222222222' + ] + clientCertificateAuthenticationValidationSchema: 'ThumbprintMatch' + description: 'this is client2' + name: 'client1' + state: 'Enabled' + } + { + clientCertificateAuthenticationAllowedThumbprints: [ + '3333333333333333333333333333333333333333' + ] + clientCertificateAuthenticationValidationSchema: 'ThumbprintMatch' + name: 'client2' + } + { + name: 'client3' + } + { + clientCertificateAuthenticationValidationSchema: 'IpMatchesAuthenticationName' + name: 'client4' + } + ] + location: '' + managedIdentities: { + userAssignedResourceIds: [ + '' + ] + } + maximumClientSessionsPerAuthenticationName: 5 + maximumSessionExpiryInHours: 2 + permissionBindings: [ + { + clientGroupName: 'group1' + description: 'this is binding1' + name: 'bindiing1' + permission: 'Publisher' + topicSpaceName: 'topicSpace1' + } + { + clientGroupName: 'group1' + name: 'bindiing2' + permission: 'Subscriber' + topicSpaceName: 'topicSpace2' + } + ] + routeTopicResourceId: '' + routingEnrichments: { + dynamic: [ + { + key: 'dynamic1' + value: '' + } + ] + static: [ + { + key: 'static1' + value: 'value1' + valueType: 'String' + } + { + key: 'static2' + value: 'value2' + valueType: 'String' + } + ] + } + routingIdentityInfo: { + type: 'UserAssigned' + userAssignedIdentity: '' + } + topics: [ + { + name: 'topic1' + } + ] + topicSpaces: [ + { + name: 'topicSpace1' + topicTemplates: [ + 'devices/foo/bar' + 'devices/topic1/+' + ] + } + { + name: 'topicSpace2' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + topicTemplates: [ + 'devices/topic1/+' + ] + } + ] + topicSpacesState: 'Enabled' + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "egnmqttct001" + }, + // Non-required parameters + "alternativeAuthenticationNameSources": { + "value": [ + "ClientCertificateEmail", + "ClientCertificateUri" + ] + }, + "clientGroups": { + "value": [ + { + "description": "this is group1", + "name": "group1", + "query": "attributes.keyName IN [\"a\", \"b\", \"c\"]" + } + ] + }, + "clients": { + "value": [ + { + "attributes": { + "deviceTypes": [ + "Fan", + "Light" + ], + "floor": 12, + "room": "345" + }, + "authenticationName": "client2auth", + "clientCertificateAuthenticationAllowedThumbprints": [ + "1111111111111111111111111111111111111111", + "2222222222222222222222222222222222222222" + ], + "clientCertificateAuthenticationValidationSchema": "ThumbprintMatch", + "description": "this is client2", + "name": "client1", + "state": "Enabled" + }, + { + "clientCertificateAuthenticationAllowedThumbprints": [ + "3333333333333333333333333333333333333333" + ], + "clientCertificateAuthenticationValidationSchema": "ThumbprintMatch", + "name": "client2" + }, + { + "name": "client3" + }, + { + "clientCertificateAuthenticationValidationSchema": "IpMatchesAuthenticationName", + "name": "client4" + } + ] + }, + "location": { + "value": "" + }, + "managedIdentities": { + "value": { + "userAssignedResourceIds": [ + "" + ] + } + }, + "maximumClientSessionsPerAuthenticationName": { + "value": 5 + }, + "maximumSessionExpiryInHours": { + "value": 2 + }, + "permissionBindings": { + "value": [ + { + "clientGroupName": "group1", + "description": "this is binding1", + "name": "bindiing1", + "permission": "Publisher", + "topicSpaceName": "topicSpace1" + }, + { + "clientGroupName": "group1", + "name": "bindiing2", + "permission": "Subscriber", + "topicSpaceName": "topicSpace2" + } + ] + }, + "routeTopicResourceId": { + "value": "" + }, + "routingEnrichments": { + "value": { + "dynamic": [ + { + "key": "dynamic1", + "value": "" + } + ], + "static": [ + { + "key": "static1", + "value": "value1", + "valueType": "String" + }, + { + "key": "static2", + "value": "value2", + "valueType": "String" + } + ] + } + }, + "routingIdentityInfo": { + "value": { + "type": "UserAssigned", + "userAssignedIdentity": "" + } + }, + "topics": { + "value": [ + { + "name": "topic1" + } + ] + }, + "topicSpaces": { + "value": [ + { + "name": "topicSpace1", + "topicTemplates": [ + "devices/foo/bar", + "devices/topic1/+" + ] + }, + { + "name": "topicSpace2", + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ], + "topicTemplates": [ + "devices/topic1/+" + ] + } + ] + }, + "topicSpacesState": { + "value": "Enabled" + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module namespace 'br/public:avm/res/event-grid/namespace:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-egnmqttnt' + params: { + // Required parameters + name: 'egnmqttnt001' + // Non-required parameters + alternativeAuthenticationNameSources: [ + 'ClientCertificateEmail' + 'ClientCertificateUri' + ] + clientGroups: [ + { + description: 'this is group1' + name: 'group1' + query: 'attributes.keyName IN [\'a\', \'b\', \'c\']' + } + ] + clients: [ + { + attributes: { + deviceTypes: [ + 'Fan' + 'Light' + ] + floor: 12 + room: '345' + } + authenticationName: 'client2auth' + clientCertificateAuthenticationAllowedThumbprints: [ + '1111111111111111111111111111111111111111' + '2222222222222222222222222222222222222222' + ] + clientCertificateAuthenticationValidationSchema: 'ThumbprintMatch' + description: 'this is client2' + name: 'client1' + state: 'Enabled' + } + { + clientCertificateAuthenticationAllowedThumbprints: [ + '3333333333333333333333333333333333333333' + ] + clientCertificateAuthenticationValidationSchema: 'ThumbprintMatch' + name: 'client2' + } + { + name: 'client3' + } + { + clientCertificateAuthenticationValidationSchema: 'IpMatchesAuthenticationName' + name: 'client4' + } + ] + location: '' + managedIdentities: { + userAssignedResourceIds: [ + '' + ] + } + maximumClientSessionsPerAuthenticationName: 5 + maximumSessionExpiryInHours: 2 + permissionBindings: [ + { + clientGroupName: 'group1' + description: 'this is binding1' + name: 'bindiing1' + permission: 'Publisher' + topicSpaceName: 'topicSpace1' + } + { + clientGroupName: 'group1' + name: 'bindiing2' + permission: 'Subscriber' + topicSpaceName: 'topicSpace2' + } + ] + routeTopicResourceId: '' + routingEnrichments: { + dynamic: [ + { + key: 'dynamic1' + value: '' + } + ] + static: [ + { + key: 'static1' + value: 'value1' + valueType: 'String' + } + { + key: 'static2' + value: 'value2' + valueType: 'String' + } + ] + } + routingIdentityInfo: { + type: 'UserAssigned' + userAssignedIdentity: '' + } + topics: [ + { + name: 'topic1' + } + ] + topicSpaces: [ + { + name: 'topicSpace1' + topicTemplates: [ + 'devices/foo/bar' + 'devices/topic1/+' + ] + } + { + name: 'topicSpace2' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + topicTemplates: [ + 'devices/topic1/+' + ] + } + ] + topicSpacesState: 'Enabled' + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "egnmqttnt001" + }, + // Non-required parameters + "alternativeAuthenticationNameSources": { + "value": [ + "ClientCertificateEmail", + "ClientCertificateUri" + ] + }, + "clientGroups": { + "value": [ + { + "description": "this is group1", + "name": "group1", + "query": "attributes.keyName IN [\"a\", \"b\", \"c\"]" + } + ] + }, + "clients": { + "value": [ + { + "attributes": { + "deviceTypes": [ + "Fan", + "Light" + ], + "floor": 12, + "room": "345" + }, + "authenticationName": "client2auth", + "clientCertificateAuthenticationAllowedThumbprints": [ + "1111111111111111111111111111111111111111", + "2222222222222222222222222222222222222222" + ], + "clientCertificateAuthenticationValidationSchema": "ThumbprintMatch", + "description": "this is client2", + "name": "client1", + "state": "Enabled" + }, + { + "clientCertificateAuthenticationAllowedThumbprints": [ + "3333333333333333333333333333333333333333" + ], + "clientCertificateAuthenticationValidationSchema": "ThumbprintMatch", + "name": "client2" + }, + { + "name": "client3" + }, + { + "clientCertificateAuthenticationValidationSchema": "IpMatchesAuthenticationName", + "name": "client4" + } + ] + }, + "location": { + "value": "" + }, + "managedIdentities": { + "value": { + "userAssignedResourceIds": [ + "" + ] + } + }, + "maximumClientSessionsPerAuthenticationName": { + "value": 5 + }, + "maximumSessionExpiryInHours": { + "value": 2 + }, + "permissionBindings": { + "value": [ + { + "clientGroupName": "group1", + "description": "this is binding1", + "name": "bindiing1", + "permission": "Publisher", + "topicSpaceName": "topicSpace1" + }, + { + "clientGroupName": "group1", + "name": "bindiing2", + "permission": "Subscriber", + "topicSpaceName": "topicSpace2" + } + ] + }, + "routeTopicResourceId": { + "value": "" + }, + "routingEnrichments": { + "value": { + "dynamic": [ + { + "key": "dynamic1", + "value": "" + } + ], + "static": [ + { + "key": "static1", + "value": "value1", + "valueType": "String" + }, + { + "key": "static2", + "value": "value2", + "valueType": "String" + } + ] + } + }, + "routingIdentityInfo": { + "value": { + "type": "UserAssigned", + "userAssignedIdentity": "" + } + }, + "topics": { + "value": [ + { + "name": "topic1" + } + ] + }, + "topicSpaces": { + "value": [ + { + "name": "topicSpace1", + "topicTemplates": [ + "devices/foo/bar", + "devices/topic1/+" + ] + }, + { + "name": "topicSpace2", + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ], + "topicTemplates": [ + "devices/topic1/+" + ] + } + ] + }, + "topicSpacesState": { + "value": "Enabled" + } + } +} +``` + +
+

+ +### 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 namespace 'br/public:avm/res/event-grid/namespace:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-egnwaf' + params: { + // Required parameters + name: 'egnwaf001' + // Non-required parameters + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + location: '' + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + '' + ] + subnetResourceId: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + { + privateDnsZoneResourceIds: [ + '' + ] + subnetResourceId: '' + } + ] + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "egnwaf001" + }, + // Non-required parameters + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "location": { + "value": "" + }, + "privateEndpoints": { + "value": [ + { + "privateDnsZoneResourceIds": [ + "" + ], + "subnetResourceId": "", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + { + "privateDnsZoneResourceIds": [ + "" + ], + "subnetResourceId": "" + } + ] + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

+ + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the Event Grid Namespace to create. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`routingIdentityInfo`](#parameter-routingidentityinfo) | object | Routing identity info for topic spaces configuration. Required if the 'routeTopicResourceId' points to a topic outside of the current Event Grid Namespace. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled') and routing is enabled ('routeTopicResourceId' is set). | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`alternativeAuthenticationNameSources`](#parameter-alternativeauthenticationnamesources) | array | Alternative authentication name sources related to client authentication settings for namespace resource. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled'). | +| [`caCertificates`](#parameter-cacertificates) | array | CA certificates (Root or intermediate) used to sign the client certificates for clients authenticated using CA-signed certificates. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled'). | +| [`clientGroups`](#parameter-clientgroups) | array | All namespace Client Groups to create. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled'). | +| [`clients`](#parameter-clients) | array | All namespace Clients to create. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled'). | +| [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`inboundIpRules`](#parameter-inboundiprules) | array | This can be used to restrict traffic from specific IPs instead of all IPs. Note: These are considered only if PublicNetworkAccess is enabled. | +| [`isZoneRedundant`](#parameter-iszoneredundant) | bool | Allows the user to specify if the namespace resource supports zone-redundancy capability or not. If this property is not specified explicitly by the user, its default value depends on the following conditions: a. For Availability Zones enabled regions - The default property value would be true. b. For non-Availability Zones enabled regions - The default property value would be false. Once specified, this property cannot be updated. | +| [`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. | +| [`maximumClientSessionsPerAuthenticationName`](#parameter-maximumclientsessionsperauthenticationname) | int | The maximum number of sessions per authentication name. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled'). | +| [`maximumSessionExpiryInHours`](#parameter-maximumsessionexpiryinhours) | int | The maximum session expiry in hours. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled'). | +| [`permissionBindings`](#parameter-permissionbindings) | array | All namespace Permission Bindings to create. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled'). | +| [`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 | This determines if traffic is allowed over public network. By default it is enabled. You can further restrict to specific IPs by configuring. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`routeTopicResourceId`](#parameter-routetopicresourceid) | string | Resource Id for the Event Grid Topic to which events will be routed to from TopicSpaces under a namespace. This enables routing of the MQTT messages to an Event Grid Topic. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled'). Note that the topic must exist prior to deployment, meaning: if referencing a topic in the same namespace, the deployment must be launched twice: 1. To create the topic 2. To enable the routing this topic. | +| [`routingEnrichments`](#parameter-routingenrichments) | object | Routing enrichments for topic spaces configuration. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled') and routing is enabled ('routeTopicResourceId' is set). | +| [`tags`](#parameter-tags) | object | Resource tags. | +| [`topics`](#parameter-topics) | array | All namespace Topics to create. | +| [`topicSpaces`](#parameter-topicspaces) | array | All namespace Topic Spaces to create. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled'). | +| [`topicSpacesState`](#parameter-topicspacesstate) | string | Indicates if Topic Spaces Configuration is enabled for the namespace. This enables the MQTT Broker functionality for the namespace. Once enabled, this property cannot be disabled. | + +### Parameter: `name` + +Name of the Event Grid Namespace to create. + +- Required: Yes +- Type: string + +### Parameter: `routingIdentityInfo` + +Routing identity info for topic spaces configuration. Required if the 'routeTopicResourceId' points to a topic outside of the current Event Grid Namespace. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled') and routing is enabled ('routeTopicResourceId' is set). + +- Required: No +- Type: object + +### Parameter: `alternativeAuthenticationNameSources` + +Alternative authentication name sources related to client authentication settings for namespace resource. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled'). + +- Required: No +- Type: array +- Allowed: + ```Bicep + [ + 'ClientCertificateDns' + 'ClientCertificateEmail' + 'ClientCertificateIp' + 'ClientCertificateSubject' + 'ClientCertificateUri' + ] + ``` + +### Parameter: `caCertificates` + +CA certificates (Root or intermediate) used to sign the client certificates for clients authenticated using CA-signed certificates. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled'). + +- Required: No +- Type: array + +### Parameter: `clientGroups` + +All namespace Client Groups to create. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled'). + +- Required: No +- Type: array + +### Parameter: `clients` + +All namespace Clients to create. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled'). + +- Required: No +- Type: array + +### Parameter: `diagnosticSettings` + +The diagnostic settings of the service. + +- Required: No +- Type: array + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`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 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. | +| [`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. | + +### Parameter: `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: `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: `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: `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. + +- Required: No +- Type: string + +### Parameter: `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-diagnosticsettingsmetriccategoriescategory) | 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-diagnosticsettingsmetriccategoriesenabled) | bool | Enable or disable the category explicitly. Default is `true`. | + +### Parameter: `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: `diagnosticSettings.metricCategories.enabled` + +Enable or disable the category explicitly. Default is `true`. + +- Required: No +- Type: bool + +### Parameter: `diagnosticSettings.name` + +The name of diagnostic setting. + +- Required: No +- Type: string + +### Parameter: `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: `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: `enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `inboundIpRules` + +This can be used to restrict traffic from specific IPs instead of all IPs. Note: These are considered only if PublicNetworkAccess is enabled. + +- Required: No +- Type: array + +### Parameter: `isZoneRedundant` + +Allows the user to specify if the namespace resource supports zone-redundancy capability or not. If this property is not specified explicitly by the user, its default value depends on the following conditions: a. For Availability Zones enabled regions - The default property value would be true. b. For non-Availability Zones enabled regions - The default property value would be false. Once specified, this property cannot be updated. + +- Required: No +- Type: bool + +### 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. + +- 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. | + +### 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: No +- Type: array + +### Parameter: `maximumClientSessionsPerAuthenticationName` + +The maximum number of sessions per authentication name. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled'). + +- Required: No +- Type: int +- Default: `1` + +### Parameter: `maximumSessionExpiryInHours` + +The maximum session expiry in hours. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled'). + +- Required: No +- Type: int +- Default: `1` + +### Parameter: `permissionBindings` + +All namespace Permission Bindings to create. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled'). + +- Required: No +- Type: array + +### Parameter: `privateEndpoints` + +Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`subnetResourceId`](#parameter-privateendpointssubnetresourceid) | string | Resource ID of the subnet where the endpoint needs to be created. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`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. | +| [`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. | +| [`isManualConnection`](#parameter-privateendpointsismanualconnection) | bool | If Manual Private Link Connection is required. | +| [`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. Restricted to 140 chars. | +| [`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. | +| [`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. | + +### Parameter: `privateEndpoints.subnetResourceId` + +Resource ID of the subnet where the endpoint needs to be created. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.applicationSecurityGroupResourceIds` + +Application security groups in which the private endpoint IP configuration is included. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.customDnsConfigs` + +Custom DNS configurations. + +- Required: No +- Type: array + +**Required parameters** + +| 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. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` + +A list of private IP addresses of the private endpoint. + +- Required: Yes +- Type: array + +### Parameter: `privateEndpoints.customNetworkInterfaceName` + +The custom name of the network interface attached to the private endpoint. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool + +### Parameter: `privateEndpoints.ipConfigurations` + +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 + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-privateendpointsipconfigurationsname) | string | The name of the resource that is unique within a resource group. | +| [`properties`](#parameter-privateendpointsipconfigurationsproperties) | object | Properties of private endpoint IP configurations. | + +### Parameter: `privateEndpoints.ipConfigurations.name` + +The name of the resource that is unique within a resource group. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.ipConfigurations.properties` + +Properties of private endpoint IP configurations. + +- Required: Yes +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`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. | + +### Parameter: `privateEndpoints.ipConfigurations.properties.groupId` + +The ID of a group obtained from the remote resource that this private endpoint should connect to. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.ipConfigurations.properties.memberName` + +The member name of a group obtained from the remote resource that this private endpoint should connect to. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.ipConfigurations.properties.privateIPAddress` + +A private IP address obtained from the private endpoint's subnet. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.isManualConnection` + +If Manual Private Link Connection is required. + +- Required: No +- Type: bool + +### Parameter: `privateEndpoints.location` + +The location to deploy the private endpoint to. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.lock` + +Specify the type of lock. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`kind`](#parameter-privateendpointslockkind) | string | Specify the type of lock. | +| [`name`](#parameter-privateendpointslockname) | string | Specify the name of lock. | + +### Parameter: `privateEndpoints.lock.kind` + +Specify the type of lock. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'CanNotDelete' + 'None' + 'ReadOnly' + ] + ``` + +### Parameter: `privateEndpoints.lock.name` + +Specify the name of lock. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.manualConnectionRequestMessage` + +A message passed to the owner of the remote resource with the manual connection request. Restricted to 140 chars. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.name` + +The name of the private endpoint. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.privateDnsZoneGroupName` + +The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.privateDnsZoneResourceIds` + +The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`principalId`](#parameter-privateendpointsroleassignmentsprincipalid) | string | The principal ID of the principal (user/group/identity) to assign the role to. | +| [`roleDefinitionIdOrName`](#parameter-privateendpointsroleassignmentsroledefinitionidorname) | 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-privateendpointsroleassignmentscondition) | 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-privateendpointsroleassignmentsconditionversion) | string | Version of the condition. | +| [`delegatedManagedIdentityResourceId`](#parameter-privateendpointsroleassignmentsdelegatedmanagedidentityresourceid) | string | The Resource Id of the delegated managed identity resource. | +| [`description`](#parameter-privateendpointsroleassignmentsdescription) | string | The description of the role assignment. | +| [`principalType`](#parameter-privateendpointsroleassignmentsprincipaltype) | string | The principal type of the assigned principal ID. | + +### Parameter: `privateEndpoints.roleAssignments.principalId` + +The principal ID of the principal (user/group/identity) to assign the role to. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.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: `privateEndpoints.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: `privateEndpoints.roleAssignments.conditionVersion` + +Version of the condition. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + '2.0' + ] + ``` + +### Parameter: `privateEndpoints.roleAssignments.delegatedManagedIdentityResourceId` + +The Resource Id of the delegated managed identity resource. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.roleAssignments.description` + +The description of the role assignment. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.roleAssignments.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `privateEndpoints.service` + +The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.tags` + +Tags to be applied on all resources/resource groups in this deployment. + +- Required: No +- Type: object + +### Parameter: `publicNetworkAccess` + +This determines if traffic is allowed over public network. By default it is enabled. You can further restrict to specific IPs by configuring. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + 'SecuredByPerimeter' + ] + ``` + +### Parameter: `roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**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. | +| [`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.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `routeTopicResourceId` + +Resource Id for the Event Grid Topic to which events will be routed to from TopicSpaces under a namespace. This enables routing of the MQTT messages to an Event Grid Topic. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled'). Note that the topic must exist prior to deployment, meaning: if referencing a topic in the same namespace, the deployment must be launched twice: 1. To create the topic 2. To enable the routing this topic. + +- Required: No +- Type: string + +### Parameter: `routingEnrichments` + +Routing enrichments for topic spaces configuration. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled') and routing is enabled ('routeTopicResourceId' is set). + +- Required: No +- Type: object + +### Parameter: `tags` + +Resource tags. + +- Required: No +- Type: object + +### Parameter: `topics` + +All namespace Topics to create. + +- Required: No +- Type: array + +### Parameter: `topicSpaces` + +All namespace Topic Spaces to create. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled'). + +- Required: No +- Type: array + +### Parameter: `topicSpacesState` + +Indicates if Topic Spaces Configuration is enabled for the namespace. This enables the MQTT Broker functionality for the namespace. Once enabled, this property cannot be disabled. + +- Required: No +- Type: string +- Default: `'Disabled'` +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the EventGrid Namespace was deployed into. | +| `name` | string | The name of the EventGrid Namespace. | +| `resourceGroupName` | string | The name of the resource group the EventGrid Namespace was created in. | +| `resourceId` | string | The resource ID of the EventGrid Namespace. | +| `systemAssignedMIPrincipalId` | string | The principal ID of the system assigned identity. | +| `topicResourceIds` | array | The Resources IDs of the EventGrid Namespace Topics. | + +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other CARML 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/network/private-endpoint:0.4.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/event-grid/namespace/ca-certificate/README.md b/avm/res/event-grid/namespace/ca-certificate/README.md new file mode 100644 index 0000000000..862b23c11c --- /dev/null +++ b/avm/res/event-grid/namespace/ca-certificate/README.md @@ -0,0 +1,83 @@ +# Eventgrid Namespace CA Certificates `[Microsoft.EventGrid/namespaces/caCertificates]` + +This module deploys an Eventgrid Namespace CA Certificate. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.EventGrid/namespaces/caCertificates` | [2023-12-15-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.EventGrid/2023-12-15-preview/namespaces/caCertificates) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`encodedCertificate`](#parameter-encodedcertificate) | string | Base64 encoded PEM (Privacy Enhanced Mail) format certificate data. | +| [`name`](#parameter-name) | string | Name of the CA certificate. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`namespaceName`](#parameter-namespacename) | string | The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`description`](#parameter-description) | string | Description for the CA Certificate resource. | + +### Parameter: `encodedCertificate` + +Base64 encoded PEM (Privacy Enhanced Mail) format certificate data. + +- Required: Yes +- Type: string + +### Parameter: `name` + +Name of the CA certificate. + +- Required: Yes +- Type: string + +### Parameter: `namespaceName` + +The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `description` + +Description for the CA Certificate resource. + +- Required: No +- Type: string + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the CA certificate. | +| `resourceGroupName` | string | The name of the resource group the CA certificate was created in. | +| `resourceId` | string | The resource ID of the CA certificate. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/event-grid/namespace/ca-certificate/main.bicep b/avm/res/event-grid/namespace/ca-certificate/main.bicep new file mode 100644 index 0000000000..14b2a8a131 --- /dev/null +++ b/avm/res/event-grid/namespace/ca-certificate/main.bicep @@ -0,0 +1,52 @@ +metadata name = 'Eventgrid Namespace CA Certificates' +metadata description = 'This module deploys an Eventgrid Namespace CA Certificate.' +metadata owner = 'Azure/module-maintainers' + +@sys.description('Conditional. The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment.') +param namespaceName string + +@sys.description('Required. Name of the CA certificate.') +param name string + +@sys.description('Optional. Description for the CA Certificate resource.') +param description string? + +@sys.description('Required. Base64 encoded PEM (Privacy Enhanced Mail) format certificate data.') +param encodedCertificate string + +// ============== // +// Resources // +// ============== // + +resource namespace 'Microsoft.EventGrid/namespaces@2023-12-15-preview' existing = { + name: namespaceName +} + +resource caCertificate 'Microsoft.EventGrid/namespaces/caCertificates@2023-12-15-preview' = { + name: name + parent: namespace + properties: { + description: description + encodedCertificate: encodedCertificate + } +} + +// ============ // +// Outputs // +// ============ // + +@sys.description('The resource ID of the CA certificate.') +output resourceId string = caCertificate.id + +@sys.description('The name of the CA certificate.') +output name string = caCertificate.name + +@sys.description('The name of the resource group the CA certificate was created in.') +output resourceGroupName string = resourceGroup().name + +// ================ // +// Definitions // +// ================ // +// +// Add your User-defined-types here, if any +// diff --git a/avm/res/event-grid/namespace/ca-certificate/main.json b/avm/res/event-grid/namespace/ca-certificate/main.json new file mode 100644 index 0000000000..16e7ad0345 --- /dev/null +++ b/avm/res/event-grid/namespace/ca-certificate/main.json @@ -0,0 +1,85 @@ +{ + "$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": "13620127830367721222" + }, + "name": "Eventgrid Namespace CA Certificates", + "description": "This module deploys an Eventgrid Namespace CA Certificate.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "namespaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the CA certificate." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Description for the CA Certificate resource." + } + }, + "encodedCertificate": { + "type": "string", + "metadata": { + "description": "Required. Base64 encoded PEM (Privacy Enhanced Mail) format certificate data." + } + } + }, + "resources": { + "namespace": { + "existing": true, + "type": "Microsoft.EventGrid/namespaces", + "apiVersion": "2023-12-15-preview", + "name": "[parameters('namespaceName')]" + }, + "caCertificate": { + "type": "Microsoft.EventGrid/namespaces/caCertificates", + "apiVersion": "2023-12-15-preview", + "name": "[format('{0}/{1}', parameters('namespaceName'), parameters('name'))]", + "properties": { + "description": "[parameters('description')]", + "encodedCertificate": "[parameters('encodedCertificate')]" + }, + "dependsOn": [ + "namespace" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the CA certificate." + }, + "value": "[resourceId('Microsoft.EventGrid/namespaces/caCertificates', parameters('namespaceName'), parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the CA certificate." + }, + "value": "[parameters('name')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the CA certificate was created in." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/event-grid/namespace/client-group/README.md b/avm/res/event-grid/namespace/client-group/README.md new file mode 100644 index 0000000000..22661aea7d --- /dev/null +++ b/avm/res/event-grid/namespace/client-group/README.md @@ -0,0 +1,83 @@ +# Eventgrid Namespace Client Groups `[Microsoft.EventGrid/namespaces/clientGroups]` + +This module deploys an Eventgrid Namespace Client Group. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.EventGrid/namespaces/clientGroups` | [2023-12-15-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.EventGrid/2023-12-15-preview/namespaces/clientGroups) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the Client Group. | +| [`query`](#parameter-query) | string | The grouping query for the clients. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`namespaceName`](#parameter-namespacename) | string | The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`description`](#parameter-description) | string | Description of the Client Group. | + +### Parameter: `name` + +Name of the Client Group. + +- Required: Yes +- Type: string + +### Parameter: `query` + +The grouping query for the clients. + +- Required: Yes +- Type: string + +### Parameter: `namespaceName` + +The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `description` + +Description of the Client Group. + +- Required: No +- Type: string + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Client Group. | +| `resourceGroupName` | string | The name of the resource group the Client Group was created in. | +| `resourceId` | string | The resource ID of the Client Group. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/event-grid/namespace/client-group/main.bicep b/avm/res/event-grid/namespace/client-group/main.bicep new file mode 100644 index 0000000000..d38830e5a4 --- /dev/null +++ b/avm/res/event-grid/namespace/client-group/main.bicep @@ -0,0 +1,52 @@ +metadata name = 'Eventgrid Namespace Client Groups' +metadata description = 'This module deploys an Eventgrid Namespace Client Group.' +metadata owner = 'Azure/module-maintainers' + +@sys.description('Conditional. The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment.') +param namespaceName string + +@sys.description('Required. Name of the Client Group.') +param name string + +@sys.description('Required. The grouping query for the clients.') +param query string + +@sys.description('Optional. Description of the Client Group.') +param description string? + +// ============== // +// Resources // +// ============== // + +resource namespace 'Microsoft.EventGrid/namespaces@2023-12-15-preview' existing = { + name: namespaceName +} + +resource clientGroup 'Microsoft.EventGrid/namespaces/clientGroups@2023-12-15-preview' = { + name: name + parent: namespace + properties: { + description: description + query: query + } +} + +// ============ // +// Outputs // +// ============ // + +@sys.description('The resource ID of the Client Group.') +output resourceId string = clientGroup.id + +@sys.description('The name of the Client Group.') +output name string = clientGroup.name + +@sys.description('The name of the resource group the Client Group was created in.') +output resourceGroupName string = resourceGroup().name + +// ================ // +// Definitions // +// ================ // +// +// Add your User-defined-types here, if any +// diff --git a/avm/res/event-grid/namespace/client-group/main.json b/avm/res/event-grid/namespace/client-group/main.json new file mode 100644 index 0000000000..125c0311f0 --- /dev/null +++ b/avm/res/event-grid/namespace/client-group/main.json @@ -0,0 +1,85 @@ +{ + "$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": "10781129401411225399" + }, + "name": "Eventgrid Namespace Client Groups", + "description": "This module deploys an Eventgrid Namespace Client Group.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "namespaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Client Group." + } + }, + "query": { + "type": "string", + "metadata": { + "description": "Required. The grouping query for the clients." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Description of the Client Group." + } + } + }, + "resources": { + "namespace": { + "existing": true, + "type": "Microsoft.EventGrid/namespaces", + "apiVersion": "2023-12-15-preview", + "name": "[parameters('namespaceName')]" + }, + "clientGroup": { + "type": "Microsoft.EventGrid/namespaces/clientGroups", + "apiVersion": "2023-12-15-preview", + "name": "[format('{0}/{1}', parameters('namespaceName'), parameters('name'))]", + "properties": { + "description": "[parameters('description')]", + "query": "[parameters('query')]" + }, + "dependsOn": [ + "namespace" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Client Group." + }, + "value": "[resourceId('Microsoft.EventGrid/namespaces/clientGroups', parameters('namespaceName'), parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the Client Group." + }, + "value": "[parameters('name')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the Client Group was created in." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/event-grid/namespace/client/README.md b/avm/res/event-grid/namespace/client/README.md new file mode 100644 index 0000000000..f10fdf6494 --- /dev/null +++ b/avm/res/event-grid/namespace/client/README.md @@ -0,0 +1,128 @@ +# Eventgrid Namespace Clients `[Microsoft.EventGrid/namespaces/clients]` + +This module deploys an Eventgrid Namespace Client. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.EventGrid/namespaces/clients` | [2023-12-15-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.EventGrid/2023-12-15-preview/namespaces/clients) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the Client. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`clientCertificateAuthenticationAllowedThumbprints`](#parameter-clientcertificateauthenticationallowedthumbprints) | array | The list of thumbprints that are allowed during client authentication. Required if the clientCertificateAuthenticationValidationSchema is 'ThumbprintMatch'. | +| [`namespaceName`](#parameter-namespacename) | string | The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`attributes`](#parameter-attributes) | object | Attributes for the client. Supported values are int, bool, string, string[]. | +| [`authenticationName`](#parameter-authenticationname) | string | The name presented by the client for authentication. The default value is the name of the resource. | +| [`clientCertificateAuthenticationValidationSchema`](#parameter-clientcertificateauthenticationvalidationschema) | string | The validation scheme used to authenticate the client. | +| [`description`](#parameter-description) | string | Description of the Client resource. | +| [`state`](#parameter-state) | string | Indicates if the client is enabled or not. | + +### Parameter: `name` + +Name of the Client. + +- Required: Yes +- Type: string + +### Parameter: `clientCertificateAuthenticationAllowedThumbprints` + +The list of thumbprints that are allowed during client authentication. Required if the clientCertificateAuthenticationValidationSchema is 'ThumbprintMatch'. + +- Required: No +- Type: array + +### Parameter: `namespaceName` + +The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `attributes` + +Attributes for the client. Supported values are int, bool, string, string[]. + +- Required: No +- Type: object + +### Parameter: `authenticationName` + +The name presented by the client for authentication. The default value is the name of the resource. + +- Required: No +- Type: string + +### Parameter: `clientCertificateAuthenticationValidationSchema` + +The validation scheme used to authenticate the client. + +- Required: No +- Type: string +- Default: `'SubjectMatchesAuthenticationName'` +- Allowed: + ```Bicep + [ + 'DnsMatchesAuthenticationName' + 'EmailMatchesAuthenticationName' + 'IpMatchesAuthenticationName' + 'SubjectMatchesAuthenticationName' + 'ThumbprintMatch' + 'UriMatchesAuthenticationName' + ] + ``` + +### Parameter: `description` + +Description of the Client resource. + +- Required: No +- Type: string + +### Parameter: `state` + +Indicates if the client is enabled or not. + +- Required: No +- Type: string +- Default: `'Enabled'` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Client. | +| `resourceGroupName` | string | The name of the resource group the Client was created in. | +| `resourceId` | string | The resource ID of the Client. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/event-grid/namespace/client/main.bicep b/avm/res/event-grid/namespace/client/main.bicep new file mode 100644 index 0000000000..f327199c31 --- /dev/null +++ b/avm/res/event-grid/namespace/client/main.bicep @@ -0,0 +1,81 @@ +metadata name = 'Eventgrid Namespace Clients' +metadata description = 'This module deploys an Eventgrid Namespace Client.' +metadata owner = 'Azure/module-maintainers' + +@sys.description('Conditional. The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment.') +param namespaceName string + +@minLength(1) +@maxLength(128) +@sys.description('Required. Name of the Client.') +param name string + +@sys.description('Optional. Description of the Client resource.') +param description string? + +@sys.description('Optional. The name presented by the client for authentication. The default value is the name of the resource.') +param authenticationName string? + +@sys.allowed([ + 'DnsMatchesAuthenticationName' + 'EmailMatchesAuthenticationName' + 'IpMatchesAuthenticationName' + 'SubjectMatchesAuthenticationName' + 'ThumbprintMatch' + 'UriMatchesAuthenticationName' + ] +) +@sys.description('Optional. The validation scheme used to authenticate the client.') +param clientCertificateAuthenticationValidationSchema string = 'SubjectMatchesAuthenticationName' + +@sys.description('Conditional. The list of thumbprints that are allowed during client authentication. Required if the clientCertificateAuthenticationValidationSchema is \'ThumbprintMatch\'.') +param clientCertificateAuthenticationAllowedThumbprints string[]? + +@sys.description('Optional. Indicates if the client is enabled or not.') +param state string = 'Enabled' + +@sys.description('Optional. Attributes for the client. Supported values are int, bool, string, string[].') +param attributes object? + +// ============== // +// Resources // +// ============== // + +resource namespace 'Microsoft.EventGrid/namespaces@2023-12-15-preview' existing = { + name: namespaceName +} + +resource client 'Microsoft.EventGrid/namespaces/clients@2023-12-15-preview' = { + name: name + parent: namespace + properties: { + description: description + authenticationName: !empty(authenticationName) ? authenticationName : name + attributes: attributes + clientCertificateAuthentication: { + validationScheme: clientCertificateAuthenticationValidationSchema + allowedThumbprints: clientCertificateAuthenticationValidationSchema == 'ThumbprintMatch' ? clientCertificateAuthenticationAllowedThumbprints : null + } + state: state + } +} + +// ============ // +// Outputs // +// ============ // + +@sys.description('The resource ID of the Client.') +output resourceId string = client.id + +@sys.description('The name of the Client.') +output name string = client.name + +@sys.description('The name of the resource group the Client was created in.') +output resourceGroupName string = resourceGroup().name + +// ================ // +// Definitions // +// ================ // +// +// Add your User-defined-types here, if any +// diff --git a/avm/res/event-grid/namespace/client/main.json b/avm/res/event-grid/namespace/client/main.json new file mode 100644 index 0000000000..0e0d7c7227 --- /dev/null +++ b/avm/res/event-grid/namespace/client/main.json @@ -0,0 +1,133 @@ +{ + "$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": "10531114495322688171" + }, + "name": "Eventgrid Namespace Clients", + "description": "This module deploys an Eventgrid Namespace Client.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "namespaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 128, + "metadata": { + "description": "Required. Name of the Client." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Description of the Client resource." + } + }, + "authenticationName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name presented by the client for authentication. The default value is the name of the resource." + } + }, + "clientCertificateAuthenticationValidationSchema": { + "type": "string", + "defaultValue": "SubjectMatchesAuthenticationName", + "allowedValues": [ + "DnsMatchesAuthenticationName", + "EmailMatchesAuthenticationName", + "IpMatchesAuthenticationName", + "SubjectMatchesAuthenticationName", + "ThumbprintMatch", + "UriMatchesAuthenticationName" + ], + "metadata": { + "description": "Optional. The validation scheme used to authenticate the client." + } + }, + "clientCertificateAuthenticationAllowedThumbprints": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Conditional. The list of thumbprints that are allowed during client authentication. Required if the clientCertificateAuthenticationValidationSchema is 'ThumbprintMatch'." + } + }, + "state": { + "type": "string", + "defaultValue": "Enabled", + "metadata": { + "description": "Optional. Indicates if the client is enabled or not." + } + }, + "attributes": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Attributes for the client. Supported values are int, bool, string, string[]." + } + } + }, + "resources": { + "namespace": { + "existing": true, + "type": "Microsoft.EventGrid/namespaces", + "apiVersion": "2023-12-15-preview", + "name": "[parameters('namespaceName')]" + }, + "client": { + "type": "Microsoft.EventGrid/namespaces/clients", + "apiVersion": "2023-12-15-preview", + "name": "[format('{0}/{1}', parameters('namespaceName'), parameters('name'))]", + "properties": { + "description": "[parameters('description')]", + "authenticationName": "[if(not(empty(parameters('authenticationName'))), parameters('authenticationName'), parameters('name'))]", + "attributes": "[parameters('attributes')]", + "clientCertificateAuthentication": { + "validationScheme": "[parameters('clientCertificateAuthenticationValidationSchema')]", + "allowedThumbprints": "[if(equals(parameters('clientCertificateAuthenticationValidationSchema'), 'ThumbprintMatch'), parameters('clientCertificateAuthenticationAllowedThumbprints'), null())]" + }, + "state": "[parameters('state')]" + }, + "dependsOn": [ + "namespace" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Client." + }, + "value": "[resourceId('Microsoft.EventGrid/namespaces/clients', parameters('namespaceName'), parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the Client." + }, + "value": "[parameters('name')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the Client was created in." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/event-grid/namespace/main.bicep b/avm/res/event-grid/namespace/main.bicep new file mode 100644 index 0000000000..d2b2581705 --- /dev/null +++ b/avm/res/event-grid/namespace/main.bicep @@ -0,0 +1,510 @@ +metadata name = 'Event Grid Namespaces' +metadata description = 'This module deploys an Event Grid Namespace.' +metadata owner = 'Azure/module-maintainers' + +@minLength(3) +@maxLength(50) +@description('Required. Name of the Event Grid Namespace to create.') +param name string + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Optional. Resource tags.') +param tags object? + +@description('Optional. Enable/Disable usage telemetry for module.') +param enableTelemetry bool = true + +@description('Optional. The managed identity definition for this resource.') +param managedIdentities managedIdentitiesType + +@description('Optional. Allows the user to specify if the namespace resource supports zone-redundancy capability or not. If this property is not specified explicitly by the user, its default value depends on the following conditions: a. For Availability Zones enabled regions - The default property value would be true. b. For non-Availability Zones enabled regions - The default property value would be false. Once specified, this property cannot be updated.') +param isZoneRedundant bool? + +@allowed([ + 'Disabled' + 'Enabled' + 'SecuredByPerimeter' +]) +@description('Optional. This determines if traffic is allowed over public network. By default it is enabled. You can further restrict to specific IPs by configuring.') +param publicNetworkAccess string? + +@description('Optional. This can be used to restrict traffic from specific IPs instead of all IPs. Note: These are considered only if PublicNetworkAccess is enabled.') +param inboundIpRules array? + +@description('Optional. The lock settings of the service.') +param lock lockType + +@description('Optional. The diagnostic settings of the service.') +param diagnosticSettings diagnosticSettingType + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +@description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') +param privateEndpoints privateEndpointType + +@allowed([ + 'Enabled' + 'Disabled' +]) +@description('Optional. Indicates if Topic Spaces Configuration is enabled for the namespace. This enables the MQTT Broker functionality for the namespace. Once enabled, this property cannot be disabled.') +param topicSpacesState string = 'Disabled' + +@allowed([ + 'ClientCertificateDns' + 'ClientCertificateEmail' + 'ClientCertificateIp' + 'ClientCertificateSubject' + 'ClientCertificateUri' +]) +@description('Optional. Alternative authentication name sources related to client authentication settings for namespace resource. Used only when MQTT broker is enabled (\'topicSpacesState\' is set to \'Enabled\').') +param alternativeAuthenticationNameSources array? + +@minValue(1) +@maxValue(8) +@description('Optional. The maximum session expiry in hours. Used only when MQTT broker is enabled (\'topicSpacesState\' is set to \'Enabled\').') +param maximumSessionExpiryInHours int = 1 + +@minValue(1) +@maxValue(100) +@description('Optional. The maximum number of sessions per authentication name. Used only when MQTT broker is enabled (\'topicSpacesState\' is set to \'Enabled\').') +param maximumClientSessionsPerAuthenticationName int = 1 + +@description('Optional. Resource Id for the Event Grid Topic to which events will be routed to from TopicSpaces under a namespace. This enables routing of the MQTT messages to an Event Grid Topic. Used only when MQTT broker is enabled (\'topicSpacesState\' is set to \'Enabled\'). Note that the topic must exist prior to deployment, meaning: if referencing a topic in the same namespace, the deployment must be launched twice: 1. To create the topic 2. To enable the routing this topic.') +param routeTopicResourceId string? + +@description('Optional. Routing enrichments for topic spaces configuration. Used only when MQTT broker is enabled (\'topicSpacesState\' is set to \'Enabled\') and routing is enabled (\'routeTopicResourceId\' is set).') +param routingEnrichments object? + +@description('Conditional. Routing identity info for topic spaces configuration. Required if the \'routeTopicResourceId\' points to a topic outside of the current Event Grid Namespace. Used only when MQTT broker is enabled (\'topicSpacesState\' is set to \'Enabled\') and routing is enabled (\'routeTopicResourceId\' is set).') +param routingIdentityInfo object? + +@description('Optional. All namespace Topics to create.') +param topics array? + +@description('Optional. CA certificates (Root or intermediate) used to sign the client certificates for clients authenticated using CA-signed certificates. Used only when MQTT broker is enabled (\'topicSpacesState\' is set to \'Enabled\').') +param caCertificates array? + +@description('Optional. All namespace Clients to create. Used only when MQTT broker is enabled (\'topicSpacesState\' is set to \'Enabled\').') +param clients array? + +@description('Optional. All namespace Client Groups to create. Used only when MQTT broker is enabled (\'topicSpacesState\' is set to \'Enabled\').') +param clientGroups array? + +@description('Optional. All namespace Topic Spaces to create. Used only when MQTT broker is enabled (\'topicSpacesState\' is set to \'Enabled\').') +param topicSpaces array? + +@description('Optional. All namespace Permission Bindings to create. Used only when MQTT broker is enabled (\'topicSpacesState\' is set to \'Enabled\').') +param permissionBindings array? + +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' : 'None') + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null +} : null + +var builtInRoleNames = { + 'Azure Resource Notifications System Topics Subscriber': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0b962ed2-6d56-471c-bd5f-3477d83a7ba4') + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'EventGrid Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1e241071-0855-49ea-94dc-649edcd759de') + 'EventGrid Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d8c3fe3-8864-474b-8749-01e3783e8157') + 'EventGrid Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '78cbd9e7-9798-4e2e-9b5a-547d9ebb31fb') + 'EventGrid Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7') + 'EventGrid EventSubscription Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443') + 'EventGrid EventSubscription Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405') + 'EventGrid TopicSpaces Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a12b0b94-b317-4dcd-84a8-502ce99884c6') + 'EventGrid TopicSpaces Subscriber': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4b0f2fd7-60b4-4eca-896f-4435034f8bf5') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +// ============== // +// Resources // +// ============== // + +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.eventgrid-namespace.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } + } + } + } +} + +resource namespace 'Microsoft.EventGrid/namespaces@2023-12-15-preview' = { + name: name + location: location + tags: tags + identity: identity + properties: { + isZoneRedundant: isZoneRedundant + publicNetworkAccess: !empty(publicNetworkAccess) ? publicNetworkAccess : (!empty(privateEndpoints) ? 'Disabled' : 'Enabled') + inboundIpRules: inboundIpRules + topicSpacesConfiguration: topicSpacesState == 'Enabled' ? { + state: topicSpacesState + clientAuthentication: !empty(alternativeAuthenticationNameSources) ? { + alternativeAuthenticationNameSources: alternativeAuthenticationNameSources + } : null + maximumSessionExpiryInHours: maximumSessionExpiryInHours + maximumClientSessionsPerAuthenticationName: maximumClientSessionsPerAuthenticationName + routeTopicResourceId: routeTopicResourceId + routingEnrichments: !empty(routeTopicResourceId) ? routingEnrichments : null + routingIdentityInfo: !empty(routeTopicResourceId) && !startsWith(routeTopicResourceId ?? '', '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.EventGrid/namespaces/${name}/topics/') ? routingIdentityInfo : null // Use routingIdentityInfo only if the topic is not in the same namespace + } : null + } +} + +resource namespace_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: namespace +} + +resource namespace_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + }] + logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + }] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: namespace +}] + +module namespace_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.1' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-namespace-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(namespace.id, '/'))}-${privateEndpoint.?service ?? 'topic'}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(namespace.id, '/'))}-${privateEndpoint.?service ?? 'topic'}-${index}' + properties: { + privateLinkServiceId: namespace.id + groupIds: [ + privateEndpoint.?service ?? 'topic' + ] + } + } + ] : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(namespace.id, '/'))}-${privateEndpoint.?service ?? 'topic'}-${index}' + properties: { + privateLinkServiceId: namespace.id + groupIds: [ + privateEndpoint.?service ?? 'topic' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } + ] : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } +}] + +resource namespace_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(namespace.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: namespace +}] + +module namespace_topics 'topic/main.bicep' = [for (topic, index) in (topics ?? []): { + name: '${uniqueString(deployment().name, location)}-Namespace-Topic-${index}' + params: { + name: topic.name + namespaceName: namespace.name + eventRetentionInDays: topic.?eventRetentionInDays + inputSchema: topic.?inputSchema + publisherType: topic.?publisherType + roleAssignments: topic.?roleAssignments + eventSubscriptions: topic.?eventSubscriptions + } +}] + +module namespace_caCertificates 'ca-certificate/main.bicep' = [for (caCertificate, index) in (caCertificates ?? []): if (topicSpacesState == 'Enabled') { + name: '${uniqueString(deployment().name, location)}-Namespace-caCertificate-${index}' + params: { + name: caCertificate.name + namespaceName: namespace.name + description: caCertificate.?description + encodedCertificate: caCertificate.encodedCertificate + } +}] + +module namespace_clients 'client/main.bicep' = [for (client, index) in (clients ?? []): if (topicSpacesState == 'Enabled') { + name: '${uniqueString(deployment().name, location)}-Namespace-Client-${index}' + params: { + name: client.name + namespaceName: namespace.name + authenticationName: client.?authenticationName + description: client.?description + clientCertificateAuthenticationValidationSchema: client.?clientCertificateAuthenticationValidationSchema + clientCertificateAuthenticationAllowedThumbprints: client.?clientCertificateAuthenticationAllowedThumbprints + attributes: client.?attributes + state: client.?state + } +}] + +module namespace_clientGroups 'client-group/main.bicep' = [for (clientGroup, index) in (clientGroups ?? []): if (topicSpacesState == 'Enabled') { + name: '${uniqueString(deployment().name, location)}-Namespace-clientGroup-${index}' + params: { + name: clientGroup.name + namespaceName: namespace.name + query: clientGroup.query + description: clientGroup.?description + } +}] + +module namespace_topicSpaces 'topic-space/main.bicep' = [for (topicSpaces, index) in (topicSpaces ?? []): if (topicSpacesState == 'Enabled') { + name: '${uniqueString(deployment().name, location)}-Namespace-topicSpace-${index}' + params: { + name: topicSpaces.name + namespaceName: namespace.name + description: topicSpaces.?description + topicTemplates: topicSpaces.topicTemplates + roleAssignments: topicSpaces.?roleAssignments + } +}] + +module namespace_permissionBindings 'permission-binding/main.bicep' = [for (permissionBinding, index) in (permissionBindings ?? []): if (topicSpacesState == 'Enabled') { + name: '${uniqueString(deployment().name, location)}-Namespace-permissionBinding-${index}' + params: { + name: permissionBinding.name + namespaceName: namespace.name + description: permissionBinding.?description + clientGroupName: permissionBinding.clientGroupName + topicSpaceName: permissionBinding.topicSpaceName + permission: permissionBinding.permission + } + dependsOn: [ + namespace_clientGroups + namespace_topicSpaces + ] +}] + +// ============ // +// Outputs // +// ============ // + +@description('The resource ID of the EventGrid Namespace.') +output resourceId string = namespace.id + +@description('The name of the EventGrid Namespace.') +output name string = namespace.name + +@description('The location the EventGrid Namespace was deployed into.') +output location string = namespace.location + +@description('The name of the resource group the EventGrid Namespace was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedMIPrincipalId string = namespace.?identity.?principalId ?? '' + +@sys.description('The Resources IDs of the EventGrid Namespace Topics.') +output topicResourceIds array = [for index in range(0, length(topics ?? [])): namespace_topics[index].outputs.resourceId] + +// ================ // +// 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('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 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. Restricted to 140 chars.') + 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? +}[]? + +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/event-grid/namespace/main.json b/avm/res/event-grid/namespace/main.json new file mode 100644 index 0000000000..61a0e2a060 --- /dev/null +++ b/avm/res/event-grid/namespace/main.json @@ -0,0 +1,2825 @@ +{ + "$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": "6122431651057596356" + }, + "name": "Event Grid Namespaces", + "description": "This module deploys an Event Grid Namespace.", + "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": { + "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." + } + }, + "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, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request. Restricted to 140 chars." + } + }, + "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." + } + } + } + }, + "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 + } + }, + "parameters": { + "name": { + "type": "string", + "minLength": 3, + "maxLength": 50, + "metadata": { + "description": "Required. Name of the Event Grid Namespace to create." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "managedIdentities": { + "$ref": "#/definitions/managedIdentitiesType", + "metadata": { + "description": "Optional. The managed identity definition for this resource." + } + }, + "isZoneRedundant": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Allows the user to specify if the namespace resource supports zone-redundancy capability or not. If this property is not specified explicitly by the user, its default value depends on the following conditions: a. For Availability Zones enabled regions - The default property value would be true. b. For non-Availability Zones enabled regions - The default property value would be false. Once specified, this property cannot be updated." + } + }, + "publicNetworkAccess": { + "type": "string", + "nullable": true, + "allowedValues": [ + "Disabled", + "Enabled", + "SecuredByPerimeter" + ], + "metadata": { + "description": "Optional. This determines if traffic is allowed over public network. By default it is enabled. You can further restrict to specific IPs by configuring." + } + }, + "inboundIpRules": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. This can be used to restrict traffic from specific IPs instead of all IPs. Note: These are considered only if PublicNetworkAccess is enabled." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic 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." + } + }, + "topicSpacesState": { + "type": "string", + "defaultValue": "Disabled", + "allowedValues": [ + "Enabled", + "Disabled" + ], + "metadata": { + "description": "Optional. Indicates if Topic Spaces Configuration is enabled for the namespace. This enables the MQTT Broker functionality for the namespace. Once enabled, this property cannot be disabled." + } + }, + "alternativeAuthenticationNameSources": { + "type": "array", + "nullable": true, + "allowedValues": [ + "ClientCertificateDns", + "ClientCertificateEmail", + "ClientCertificateIp", + "ClientCertificateSubject", + "ClientCertificateUri" + ], + "metadata": { + "description": "Optional. Alternative authentication name sources related to client authentication settings for namespace resource. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled')." + } + }, + "maximumSessionExpiryInHours": { + "type": "int", + "defaultValue": 1, + "minValue": 1, + "maxValue": 8, + "metadata": { + "description": "Optional. The maximum session expiry in hours. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled')." + } + }, + "maximumClientSessionsPerAuthenticationName": { + "type": "int", + "defaultValue": 1, + "minValue": 1, + "maxValue": 100, + "metadata": { + "description": "Optional. The maximum number of sessions per authentication name. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled')." + } + }, + "routeTopicResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource Id for the Event Grid Topic to which events will be routed to from TopicSpaces under a namespace. This enables routing of the MQTT messages to an Event Grid Topic. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled'). Note that the topic must exist prior to deployment, meaning: if referencing a topic in the same namespace, the deployment must be launched twice: 1. To create the topic 2. To enable the routing this topic." + } + }, + "routingEnrichments": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Routing enrichments for topic spaces configuration. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled') and routing is enabled ('routeTopicResourceId' is set)." + } + }, + "routingIdentityInfo": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Conditional. Routing identity info for topic spaces configuration. Required if the 'routeTopicResourceId' points to a topic outside of the current Event Grid Namespace. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled') and routing is enabled ('routeTopicResourceId' is set)." + } + }, + "topics": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. All namespace Topics to create." + } + }, + "caCertificates": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. CA certificates (Root or intermediate) used to sign the client certificates for clients authenticated using CA-signed certificates. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled')." + } + }, + "clients": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. All namespace Clients to create. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled')." + } + }, + "clientGroups": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. All namespace Client Groups to create. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled')." + } + }, + "topicSpaces": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. All namespace Topic Spaces to create. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled')." + } + }, + "permissionBindings": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. All namespace Permission Bindings to create. Used only when MQTT broker is enabled ('topicSpacesState' is set to 'Enabled')." + } + } + }, + "variables": { + "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 Resource Notifications System Topics Subscriber": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0b962ed2-6d56-471c-bd5f-3477d83a7ba4')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "EventGrid Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1e241071-0855-49ea-94dc-649edcd759de')]", + "EventGrid Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d8c3fe3-8864-474b-8749-01e3783e8157')]", + "EventGrid Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '78cbd9e7-9798-4e2e-9b5a-547d9ebb31fb')]", + "EventGrid Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7')]", + "EventGrid EventSubscription Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443')]", + "EventGrid EventSubscription Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405')]", + "EventGrid TopicSpaces Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a12b0b94-b317-4dcd-84a8-502ce99884c6')]", + "EventGrid TopicSpaces Subscriber": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4b0f2fd7-60b4-4eca-896f-4435034f8bf5')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.eventgrid-namespace.{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" + } + } + } + } + }, + "namespace": { + "type": "Microsoft.EventGrid/namespaces", + "apiVersion": "2023-12-15-preview", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": "[variables('identity')]", + "properties": { + "isZoneRedundant": "[parameters('isZoneRedundant')]", + "publicNetworkAccess": "[if(not(empty(parameters('publicNetworkAccess'))), parameters('publicNetworkAccess'), if(not(empty(parameters('privateEndpoints'))), 'Disabled', 'Enabled'))]", + "inboundIpRules": "[parameters('inboundIpRules')]", + "topicSpacesConfiguration": "[if(equals(parameters('topicSpacesState'), 'Enabled'), createObject('state', parameters('topicSpacesState'), 'clientAuthentication', if(not(empty(parameters('alternativeAuthenticationNameSources'))), createObject('alternativeAuthenticationNameSources', parameters('alternativeAuthenticationNameSources')), null()), 'maximumSessionExpiryInHours', parameters('maximumSessionExpiryInHours'), 'maximumClientSessionsPerAuthenticationName', parameters('maximumClientSessionsPerAuthenticationName'), 'routeTopicResourceId', parameters('routeTopicResourceId'), 'routingEnrichments', if(not(empty(parameters('routeTopicResourceId'))), parameters('routingEnrichments'), null()), 'routingIdentityInfo', if(and(not(empty(parameters('routeTopicResourceId'))), not(startsWith(coalesce(parameters('routeTopicResourceId'), ''), format('/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.EventGrid/namespaces/{2}/topics/', subscription().subscriptionId, resourceGroup().name, parameters('name'))))), parameters('routingIdentityInfo'), null())), null())]" + } + }, + "namespace_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.EventGrid/namespaces/{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": [ + "namespace" + ] + }, + "namespace_diagnosticSettings": { + "copy": { + "name": "namespace_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.EventGrid/namespaces/{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": [ + "namespace" + ] + }, + "namespace_roleAssignments": { + "copy": { + "name": "namespace_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.EventGrid/namespaces/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.EventGrid/namespaces', 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": [ + "namespace" + ] + }, + "namespace_privateEndpoints": { + "copy": { + "name": "namespace_privateEndpoints", + "count": "[length(coalesce(parameters('privateEndpoints'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-namespace-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "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.EventGrid/namespaces', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'topic'), copyIndex()))]" + }, + "privateLinkServiceConnections": "[if(not(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections'), true())), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.EventGrid/namespaces', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'topic'), copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.EventGrid/namespaces', parameters('name')), 'groupIds', createArray(coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'topic')))))), createObject('value', null()))]", + "manualPrivateLinkServiceConnections": "[if(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections'), true()), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.EventGrid/namespaces', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'topic'), copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.EventGrid/namespaces', parameters('name')), 'groupIds', createArray(coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'topic')), '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'))]" + }, + "privateDnsZoneGroupName": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneGroupName')]" + }, + "privateDnsZoneResourceIds": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneResourceIds')]" + }, + "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.25.53.49325", + "templateHash": "4120048060064073955" + }, + "name": "Private Endpoints", + "description": "This module deploys a Private Endpoint.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "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." + } + }, + "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 + }, + "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", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "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", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "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 + } + }, + "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." + } + }, + "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", + "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." + } + }, + "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": { + "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": "2023-07-01", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.4.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-04-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(parameters('roleAssignments'), 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)]", + "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": [ + "privateEndpoint" + ] + }, + "privateEndpoint_privateDnsZoneGroup": { + "condition": "[not(empty(parameters('privateDnsZoneResourceIds')))]", + "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": "[coalesce(parameters('privateDnsZoneGroupName'), 'default')]" + }, + "privateDNSResourceIds": { + "value": "[coalesce(parameters('privateDnsZoneResourceIds'), createArray())]" + }, + "privateEndpointName": { + "value": "[parameters('name')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "11244630631275470040" + }, + "name": "Private Endpoint Private DNS Zone Groups", + "description": "This module deploys a Private Endpoint Private DNS Zone Group.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "privateEndpointName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent private endpoint. Required if the template is used in a standalone deployment." + } + }, + "privateDNSResourceIds": { + "type": "array", + "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." + } + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the private DNS zone group." + } + } + }, + "variables": { + "copy": [ + { + "name": "privateDnsZoneConfigs", + "count": "[length(parameters('privateDNSResourceIds'))]", + "input": { + "name": "[last(split(parameters('privateDNSResourceIds')[copyIndex('privateDnsZoneConfigs')], '/'))]", + "properties": { + "privateDnsZoneId": "[parameters('privateDNSResourceIds')[copyIndex('privateDnsZoneConfigs')]]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2023-04-01", + "name": "[format('{0}/{1}', parameters('privateEndpointName'), parameters('name'))]", + "properties": { + "privateDnsZoneConfigs": "[variables('privateDnsZoneConfigs')]" + } + } + ], + "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-04-01', 'full').location]" + }, + "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])]" + } + } + } + }, + "dependsOn": [ + "namespace" + ] + }, + "namespace_topics": { + "copy": { + "name": "namespace_topics", + "count": "[length(coalesce(parameters('topics'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Namespace-Topic-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(parameters('topics'), createArray())[copyIndex()].name]" + }, + "namespaceName": { + "value": "[parameters('name')]" + }, + "eventRetentionInDays": { + "value": "[tryGet(coalesce(parameters('topics'), createArray())[copyIndex()], 'eventRetentionInDays')]" + }, + "inputSchema": { + "value": "[tryGet(coalesce(parameters('topics'), createArray())[copyIndex()], 'inputSchema')]" + }, + "publisherType": { + "value": "[tryGet(coalesce(parameters('topics'), createArray())[copyIndex()], 'publisherType')]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('topics'), createArray())[copyIndex()], 'roleAssignments')]" + }, + "eventSubscriptions": { + "value": "[tryGet(coalesce(parameters('topics'), createArray())[copyIndex()], 'eventSubscriptions')]" + } + }, + "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": "2836208779363789051" + }, + "name": "Eventgrid Namespace Topics", + "description": "This module deploys an Eventgrid Namespace Topic.", + "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": { + "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": { + "namespaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the topic." + } + }, + "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." + } + }, + "eventRetentionInDays": { + "type": "int", + "defaultValue": 1, + "minValue": 1, + "maxValue": 7, + "metadata": { + "description": "Optional. Event retention for the namespace topic expressed in days." + } + }, + "inputSchema": { + "type": "string", + "defaultValue": "CloudEventSchemaV1_0", + "metadata": { + "description": "Optional. This determines the format that is expected for incoming events published to the topic." + } + }, + "publisherType": { + "type": "string", + "defaultValue": "Custom", + "metadata": { + "description": "Optional. Publisher type of the namespace topic." + } + }, + "eventSubscriptions": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. All event subscriptions to create." + } + } + }, + "variables": { + "builtInRoleNames": { + "Azure Resource Notifications System Topics Subscriber": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0b962ed2-6d56-471c-bd5f-3477d83a7ba4')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "EventGrid Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1e241071-0855-49ea-94dc-649edcd759de')]", + "EventGrid Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d8c3fe3-8864-474b-8749-01e3783e8157')]", + "EventGrid Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '78cbd9e7-9798-4e2e-9b5a-547d9ebb31fb')]", + "EventGrid Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7')]", + "EventGrid EventSubscription Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443')]", + "EventGrid EventSubscription Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405')]", + "EventGrid TopicSpaces Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a12b0b94-b317-4dcd-84a8-502ce99884c6')]", + "EventGrid TopicSpaces Subscriber": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4b0f2fd7-60b4-4eca-896f-4435034f8bf5')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "namespace": { + "existing": true, + "type": "Microsoft.EventGrid/namespaces", + "apiVersion": "2023-12-15-preview", + "name": "[parameters('namespaceName')]" + }, + "topic": { + "type": "Microsoft.EventGrid/namespaces/topics", + "apiVersion": "2023-12-15-preview", + "name": "[format('{0}/{1}', parameters('namespaceName'), parameters('name'))]", + "properties": { + "eventRetentionInDays": "[parameters('eventRetentionInDays')]", + "inputSchema": "[parameters('inputSchema')]", + "publisherType": "[parameters('publisherType')]" + }, + "dependsOn": [ + "namespace" + ] + }, + "topic_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.EventGrid/namespaces/{0}/topics/{1}', parameters('namespaceName'), 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": [ + "topic" + ] + }, + "topic_roleAssignments": { + "copy": { + "name": "topic_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.EventGrid/namespaces/{0}/topics/{1}', parameters('namespaceName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.EventGrid/namespaces/topics', parameters('namespaceName'), 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": [ + "topic" + ] + }, + "topic_eventSubscriptions": { + "copy": { + "name": "topic_eventSubscriptions", + "count": "[length(coalesce(parameters('eventSubscriptions'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Topic-EventSubscription-{1}', uniqueString(deployment().name, parameters('name')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(parameters('eventSubscriptions'), createArray())[copyIndex()].name]" + }, + "namespaceName": { + "value": "[parameters('namespaceName')]" + }, + "topicName": { + "value": "[parameters('name')]" + }, + "deliveryConfiguration": { + "value": "[tryGet(coalesce(parameters('eventSubscriptions'), createArray())[copyIndex()], 'deliveryConfiguration')]" + }, + "eventDeliverySchema": { + "value": "[tryGet(coalesce(parameters('eventSubscriptions'), createArray())[copyIndex()], 'eventDeliverySchema')]" + }, + "filtersConfiguration": { + "value": "[tryGet(coalesce(parameters('eventSubscriptions'), createArray())[copyIndex()], 'filtersConfiguration')]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('eventSubscriptions'), 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.25.53.49325", + "templateHash": "13130499975324434363" + }, + "name": "Event Subscriptions", + "description": "This module deploys an Event Subscription.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "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": { + "namespaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment." + } + }, + "topicName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent EventGrid namespace topic. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Event Subscription to create." + } + }, + "deliveryConfiguration": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Information about the delivery configuration of the Event Subscription." + } + }, + "eventDeliverySchema": { + "type": "string", + "defaultValue": "CloudEventSchemaV1_0", + "metadata": { + "description": "Optional. The event delivery schema for the Event Subscription." + } + }, + "filtersConfiguration": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Information about the filter for the Event Subscription." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "builtInRoleNames": { + "Azure Resource Notifications System Topics Subscriber": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0b962ed2-6d56-471c-bd5f-3477d83a7ba4')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "EventGrid Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1e241071-0855-49ea-94dc-649edcd759de')]", + "EventGrid Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d8c3fe3-8864-474b-8749-01e3783e8157')]", + "EventGrid Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '78cbd9e7-9798-4e2e-9b5a-547d9ebb31fb')]", + "EventGrid Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7')]", + "EventGrid EventSubscription Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443')]", + "EventGrid EventSubscription Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405')]", + "EventGrid TopicSpaces Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a12b0b94-b317-4dcd-84a8-502ce99884c6')]", + "EventGrid TopicSpaces Subscriber": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4b0f2fd7-60b4-4eca-896f-4435034f8bf5')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "namespace::topic": { + "existing": true, + "type": "Microsoft.EventGrid/namespaces/topics", + "apiVersion": "2023-12-15-preview", + "name": "[format('{0}/{1}', parameters('namespaceName'), parameters('topicName'))]", + "dependsOn": [ + "namespace" + ] + }, + "namespace": { + "existing": true, + "type": "Microsoft.EventGrid/namespaces", + "apiVersion": "2023-12-15-preview", + "name": "[parameters('namespaceName')]" + }, + "eventSubscription": { + "type": "Microsoft.EventGrid/namespaces/topics/eventSubscriptions", + "apiVersion": "2023-12-15-preview", + "name": "[format('{0}/{1}/{2}', parameters('namespaceName'), parameters('topicName'), parameters('name'))]", + "properties": { + "deliveryConfiguration": "[parameters('deliveryConfiguration')]", + "eventDeliverySchema": "[parameters('eventDeliverySchema')]", + "filtersConfiguration": "[parameters('filtersConfiguration')]" + }, + "dependsOn": [ + "namespace::topic" + ] + }, + "eventSubscription_roleAssignments": { + "copy": { + "name": "eventSubscription_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.EventGrid/namespaces/{0}/topics/{1}/eventSubscriptions/{2}', parameters('namespaceName'), parameters('topicName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.EventGrid/namespaces/topics/eventSubscriptions', parameters('namespaceName'), parameters('topicName'), 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": [ + "eventSubscription" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Event Subscription." + }, + "value": "[resourceId('Microsoft.EventGrid/namespaces/topics/eventSubscriptions', parameters('namespaceName'), parameters('topicName'), parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the Event Subscription." + }, + "value": "[parameters('name')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the Event Subscription was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "namespace", + "topic" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Namespace Topic." + }, + "value": "[resourceId('Microsoft.EventGrid/namespaces/topics', parameters('namespaceName'), parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the Namespace Topic." + }, + "value": "[parameters('name')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the Namespace Topic was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "namespace" + ] + }, + "namespace_caCertificates": { + "copy": { + "name": "namespace_caCertificates", + "count": "[length(coalesce(parameters('caCertificates'), createArray()))]" + }, + "condition": "[equals(parameters('topicSpacesState'), 'Enabled')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Namespace-caCertificate-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(parameters('caCertificates'), createArray())[copyIndex()].name]" + }, + "namespaceName": { + "value": "[parameters('name')]" + }, + "description": { + "value": "[tryGet(coalesce(parameters('caCertificates'), createArray())[copyIndex()], 'description')]" + }, + "encodedCertificate": { + "value": "[coalesce(parameters('caCertificates'), createArray())[copyIndex()].encodedCertificate]" + } + }, + "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": "13620127830367721222" + }, + "name": "Eventgrid Namespace CA Certificates", + "description": "This module deploys an Eventgrid Namespace CA Certificate.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "namespaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the CA certificate." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Description for the CA Certificate resource." + } + }, + "encodedCertificate": { + "type": "string", + "metadata": { + "description": "Required. Base64 encoded PEM (Privacy Enhanced Mail) format certificate data." + } + } + }, + "resources": { + "namespace": { + "existing": true, + "type": "Microsoft.EventGrid/namespaces", + "apiVersion": "2023-12-15-preview", + "name": "[parameters('namespaceName')]" + }, + "caCertificate": { + "type": "Microsoft.EventGrid/namespaces/caCertificates", + "apiVersion": "2023-12-15-preview", + "name": "[format('{0}/{1}', parameters('namespaceName'), parameters('name'))]", + "properties": { + "description": "[parameters('description')]", + "encodedCertificate": "[parameters('encodedCertificate')]" + }, + "dependsOn": [ + "namespace" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the CA certificate." + }, + "value": "[resourceId('Microsoft.EventGrid/namespaces/caCertificates', parameters('namespaceName'), parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the CA certificate." + }, + "value": "[parameters('name')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the CA certificate was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "namespace" + ] + }, + "namespace_clients": { + "copy": { + "name": "namespace_clients", + "count": "[length(coalesce(parameters('clients'), createArray()))]" + }, + "condition": "[equals(parameters('topicSpacesState'), 'Enabled')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Namespace-Client-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(parameters('clients'), createArray())[copyIndex()].name]" + }, + "namespaceName": { + "value": "[parameters('name')]" + }, + "authenticationName": { + "value": "[tryGet(coalesce(parameters('clients'), createArray())[copyIndex()], 'authenticationName')]" + }, + "description": { + "value": "[tryGet(coalesce(parameters('clients'), createArray())[copyIndex()], 'description')]" + }, + "clientCertificateAuthenticationValidationSchema": { + "value": "[tryGet(coalesce(parameters('clients'), createArray())[copyIndex()], 'clientCertificateAuthenticationValidationSchema')]" + }, + "clientCertificateAuthenticationAllowedThumbprints": { + "value": "[tryGet(coalesce(parameters('clients'), createArray())[copyIndex()], 'clientCertificateAuthenticationAllowedThumbprints')]" + }, + "attributes": { + "value": "[tryGet(coalesce(parameters('clients'), createArray())[copyIndex()], 'attributes')]" + }, + "state": { + "value": "[tryGet(coalesce(parameters('clients'), createArray())[copyIndex()], 'state')]" + } + }, + "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": "10531114495322688171" + }, + "name": "Eventgrid Namespace Clients", + "description": "This module deploys an Eventgrid Namespace Client.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "namespaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 128, + "metadata": { + "description": "Required. Name of the Client." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Description of the Client resource." + } + }, + "authenticationName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name presented by the client for authentication. The default value is the name of the resource." + } + }, + "clientCertificateAuthenticationValidationSchema": { + "type": "string", + "defaultValue": "SubjectMatchesAuthenticationName", + "allowedValues": [ + "DnsMatchesAuthenticationName", + "EmailMatchesAuthenticationName", + "IpMatchesAuthenticationName", + "SubjectMatchesAuthenticationName", + "ThumbprintMatch", + "UriMatchesAuthenticationName" + ], + "metadata": { + "description": "Optional. The validation scheme used to authenticate the client." + } + }, + "clientCertificateAuthenticationAllowedThumbprints": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Conditional. The list of thumbprints that are allowed during client authentication. Required if the clientCertificateAuthenticationValidationSchema is 'ThumbprintMatch'." + } + }, + "state": { + "type": "string", + "defaultValue": "Enabled", + "metadata": { + "description": "Optional. Indicates if the client is enabled or not." + } + }, + "attributes": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Attributes for the client. Supported values are int, bool, string, string[]." + } + } + }, + "resources": { + "namespace": { + "existing": true, + "type": "Microsoft.EventGrid/namespaces", + "apiVersion": "2023-12-15-preview", + "name": "[parameters('namespaceName')]" + }, + "client": { + "type": "Microsoft.EventGrid/namespaces/clients", + "apiVersion": "2023-12-15-preview", + "name": "[format('{0}/{1}', parameters('namespaceName'), parameters('name'))]", + "properties": { + "description": "[parameters('description')]", + "authenticationName": "[if(not(empty(parameters('authenticationName'))), parameters('authenticationName'), parameters('name'))]", + "attributes": "[parameters('attributes')]", + "clientCertificateAuthentication": { + "validationScheme": "[parameters('clientCertificateAuthenticationValidationSchema')]", + "allowedThumbprints": "[if(equals(parameters('clientCertificateAuthenticationValidationSchema'), 'ThumbprintMatch'), parameters('clientCertificateAuthenticationAllowedThumbprints'), null())]" + }, + "state": "[parameters('state')]" + }, + "dependsOn": [ + "namespace" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Client." + }, + "value": "[resourceId('Microsoft.EventGrid/namespaces/clients', parameters('namespaceName'), parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the Client." + }, + "value": "[parameters('name')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the Client was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "namespace" + ] + }, + "namespace_clientGroups": { + "copy": { + "name": "namespace_clientGroups", + "count": "[length(coalesce(parameters('clientGroups'), createArray()))]" + }, + "condition": "[equals(parameters('topicSpacesState'), 'Enabled')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Namespace-clientGroup-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(parameters('clientGroups'), createArray())[copyIndex()].name]" + }, + "namespaceName": { + "value": "[parameters('name')]" + }, + "query": { + "value": "[coalesce(parameters('clientGroups'), createArray())[copyIndex()].query]" + }, + "description": { + "value": "[tryGet(coalesce(parameters('clientGroups'), createArray())[copyIndex()], 'description')]" + } + }, + "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": "10781129401411225399" + }, + "name": "Eventgrid Namespace Client Groups", + "description": "This module deploys an Eventgrid Namespace Client Group.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "namespaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Client Group." + } + }, + "query": { + "type": "string", + "metadata": { + "description": "Required. The grouping query for the clients." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Description of the Client Group." + } + } + }, + "resources": { + "namespace": { + "existing": true, + "type": "Microsoft.EventGrid/namespaces", + "apiVersion": "2023-12-15-preview", + "name": "[parameters('namespaceName')]" + }, + "clientGroup": { + "type": "Microsoft.EventGrid/namespaces/clientGroups", + "apiVersion": "2023-12-15-preview", + "name": "[format('{0}/{1}', parameters('namespaceName'), parameters('name'))]", + "properties": { + "description": "[parameters('description')]", + "query": "[parameters('query')]" + }, + "dependsOn": [ + "namespace" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Client Group." + }, + "value": "[resourceId('Microsoft.EventGrid/namespaces/clientGroups', parameters('namespaceName'), parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the Client Group." + }, + "value": "[parameters('name')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the Client Group was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "namespace" + ] + }, + "namespace_topicSpaces": { + "copy": { + "name": "namespace_topicSpaces", + "count": "[length(coalesce(parameters('topicSpaces'), createArray()))]" + }, + "condition": "[equals(parameters('topicSpacesState'), 'Enabled')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Namespace-topicSpace-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(parameters('topicSpaces'), createArray())[copyIndex()].name]" + }, + "namespaceName": { + "value": "[parameters('name')]" + }, + "description": { + "value": "[tryGet(coalesce(parameters('topicSpaces'), createArray())[copyIndex()], 'description')]" + }, + "topicTemplates": { + "value": "[coalesce(parameters('topicSpaces'), createArray())[copyIndex()].topicTemplates]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('topicSpaces'), 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.25.53.49325", + "templateHash": "6548696237893842735" + }, + "name": "Eventgrid Namespace Topic Spaces", + "description": "This module deploys an Eventgrid Namespace Topic Space.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "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": { + "namespaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Topic Space." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Description of the Topic Space." + } + }, + "topicTemplates": { + "type": "array", + "minLength": 1, + "metadata": { + "description": "Required. The topic filters in the Topic Space." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "builtInRoleNames": { + "Azure Resource Notifications System Topics Subscriber": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0b962ed2-6d56-471c-bd5f-3477d83a7ba4')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "EventGrid Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1e241071-0855-49ea-94dc-649edcd759de')]", + "EventGrid Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d8c3fe3-8864-474b-8749-01e3783e8157')]", + "EventGrid Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '78cbd9e7-9798-4e2e-9b5a-547d9ebb31fb')]", + "EventGrid Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7')]", + "EventGrid EventSubscription Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443')]", + "EventGrid EventSubscription Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405')]", + "EventGrid TopicSpaces Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a12b0b94-b317-4dcd-84a8-502ce99884c6')]", + "EventGrid TopicSpaces Subscriber": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4b0f2fd7-60b4-4eca-896f-4435034f8bf5')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "namespace": { + "existing": true, + "type": "Microsoft.EventGrid/namespaces", + "apiVersion": "2023-12-15-preview", + "name": "[parameters('namespaceName')]" + }, + "topicSpace": { + "type": "Microsoft.EventGrid/namespaces/topicSpaces", + "apiVersion": "2023-12-15-preview", + "name": "[format('{0}/{1}', parameters('namespaceName'), parameters('name'))]", + "properties": { + "description": "[parameters('description')]", + "topicTemplates": "[parameters('topicTemplates')]" + }, + "dependsOn": [ + "namespace" + ] + }, + "topic_roleAssignments": { + "copy": { + "name": "topic_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.EventGrid/namespaces/{0}/topicSpaces/{1}', parameters('namespaceName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.EventGrid/namespaces/topicSpaces', parameters('namespaceName'), 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": [ + "topicSpace" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Topic Space." + }, + "value": "[resourceId('Microsoft.EventGrid/namespaces/topicSpaces', parameters('namespaceName'), parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the Topic Space." + }, + "value": "[parameters('name')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the Topic Space was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "namespace" + ] + }, + "namespace_permissionBindings": { + "copy": { + "name": "namespace_permissionBindings", + "count": "[length(coalesce(parameters('permissionBindings'), createArray()))]" + }, + "condition": "[equals(parameters('topicSpacesState'), 'Enabled')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Namespace-permissionBinding-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(parameters('permissionBindings'), createArray())[copyIndex()].name]" + }, + "namespaceName": { + "value": "[parameters('name')]" + }, + "description": { + "value": "[tryGet(coalesce(parameters('permissionBindings'), createArray())[copyIndex()], 'description')]" + }, + "clientGroupName": { + "value": "[coalesce(parameters('permissionBindings'), createArray())[copyIndex()].clientGroupName]" + }, + "topicSpaceName": { + "value": "[coalesce(parameters('permissionBindings'), createArray())[copyIndex()].topicSpaceName]" + }, + "permission": { + "value": "[coalesce(parameters('permissionBindings'), createArray())[copyIndex()].permission]" + } + }, + "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": "5622068529761827218" + }, + "name": "Eventgrid Namespace Permissions Bindings", + "description": "This module deploys an Eventgrid Namespace Permission Binding.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "namespaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Permission Binding." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Description of the Permission Binding." + } + }, + "clientGroupName": { + "type": "string", + "metadata": { + "description": "Required. The name of the client group resource that the permission is bound to. The client group needs to be a resource under the same namespace the permission binding is a part of." + } + }, + "topicSpaceName": { + "type": "string", + "metadata": { + "description": "Required. The name of the Topic Space resource that the permission is bound to. The Topic space needs to be a resource under the same namespace the permission binding is a part of." + } + }, + "permission": { + "type": "string", + "allowedValues": [ + "Publisher", + "Subscriber" + ], + "metadata": { + "description": "Required. The allowed permission." + } + } + }, + "resources": { + "namespace": { + "existing": true, + "type": "Microsoft.EventGrid/namespaces", + "apiVersion": "2023-12-15-preview", + "name": "[parameters('namespaceName')]" + }, + "permissionBinding": { + "type": "Microsoft.EventGrid/namespaces/permissionBindings", + "apiVersion": "2023-12-15-preview", + "name": "[format('{0}/{1}', parameters('namespaceName'), parameters('name'))]", + "properties": { + "clientGroupName": "[parameters('clientGroupName')]", + "description": "[parameters('description')]", + "permission": "[parameters('permission')]", + "topicSpaceName": "[parameters('topicSpaceName')]" + }, + "dependsOn": [ + "namespace" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Permission Binding." + }, + "value": "[resourceId('Microsoft.EventGrid/namespaces/permissionBindings', parameters('namespaceName'), parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the Permission Binding." + }, + "value": "[parameters('name')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the Permission Binding was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "namespace", + "namespace_clientGroups", + "namespace_topicSpaces" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the EventGrid Namespace." + }, + "value": "[resourceId('Microsoft.EventGrid/namespaces', parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the EventGrid Namespace." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the EventGrid Namespace was deployed into." + }, + "value": "[reference('namespace', '2023-12-15-preview', 'full').location]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the EventGrid Namespace was created in." + }, + "value": "[resourceGroup().name]" + }, + "systemAssignedMIPrincipalId": { + "type": "string", + "metadata": { + "description": "The principal ID of the system assigned identity." + }, + "value": "[coalesce(tryGet(tryGet(reference('namespace', '2023-12-15-preview', 'full'), 'identity'), 'principalId'), '')]" + }, + "topicResourceIds": { + "type": "array", + "metadata": { + "description": "The Resources IDs of the EventGrid Namespace Topics." + }, + "copy": { + "count": "[length(range(0, length(coalesce(parameters('topics'), createArray()))))]", + "input": "[reference(format('namespace_topics[{0}]', range(0, length(coalesce(parameters('topics'), createArray())))[copyIndex()])).outputs.resourceId.value]" + } + } + } +} \ No newline at end of file diff --git a/avm/res/event-grid/namespace/permission-binding/README.md b/avm/res/event-grid/namespace/permission-binding/README.md new file mode 100644 index 0000000000..ac57f00b03 --- /dev/null +++ b/avm/res/event-grid/namespace/permission-binding/README.md @@ -0,0 +1,106 @@ +# Eventgrid Namespace Permissions Bindings `[Microsoft.EventGrid/namespaces/permissionBindings]` + +This module deploys an Eventgrid Namespace Permission Binding. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.EventGrid/namespaces/permissionBindings` | [2023-12-15-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.EventGrid/2023-12-15-preview/namespaces/permissionBindings) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`clientGroupName`](#parameter-clientgroupname) | string | The name of the client group resource that the permission is bound to. The client group needs to be a resource under the same namespace the permission binding is a part of. | +| [`name`](#parameter-name) | string | Name of the Permission Binding. | +| [`permission`](#parameter-permission) | string | The allowed permission. | +| [`topicSpaceName`](#parameter-topicspacename) | string | The name of the Topic Space resource that the permission is bound to. The Topic space needs to be a resource under the same namespace the permission binding is a part of. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`namespaceName`](#parameter-namespacename) | string | The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`description`](#parameter-description) | string | Description of the Permission Binding. | + +### Parameter: `clientGroupName` + +The name of the client group resource that the permission is bound to. The client group needs to be a resource under the same namespace the permission binding is a part of. + +- Required: Yes +- Type: string + +### Parameter: `name` + +Name of the Permission Binding. + +- Required: Yes +- Type: string + +### Parameter: `permission` + +The allowed permission. + +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'Publisher' + 'Subscriber' + ] + ``` + +### Parameter: `topicSpaceName` + +The name of the Topic Space resource that the permission is bound to. The Topic space needs to be a resource under the same namespace the permission binding is a part of. + +- Required: Yes +- Type: string + +### Parameter: `namespaceName` + +The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `description` + +Description of the Permission Binding. + +- Required: No +- Type: string + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Permission Binding. | +| `resourceGroupName` | string | The name of the resource group the Permission Binding was created in. | +| `resourceId` | string | The resource ID of the Permission Binding. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/event-grid/namespace/permission-binding/main.bicep b/avm/res/event-grid/namespace/permission-binding/main.bicep new file mode 100644 index 0000000000..5d085148ef --- /dev/null +++ b/avm/res/event-grid/namespace/permission-binding/main.bicep @@ -0,0 +1,64 @@ +metadata name = 'Eventgrid Namespace Permissions Bindings' +metadata description = 'This module deploys an Eventgrid Namespace Permission Binding.' +metadata owner = 'Azure/module-maintainers' + +@sys.description('Conditional. The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment.') +param namespaceName string + +@sys.description('Required. Name of the Permission Binding.') +param name string + +@sys.description('Optional. Description of the Permission Binding.') +param description string? + +@sys.description('Required. The name of the client group resource that the permission is bound to. The client group needs to be a resource under the same namespace the permission binding is a part of.') +param clientGroupName string + +@sys.description('Required. The name of the Topic Space resource that the permission is bound to. The Topic space needs to be a resource under the same namespace the permission binding is a part of.') +param topicSpaceName string + +@allowed([ + 'Publisher' + 'Subscriber' +]) +@sys.description('Required. The allowed permission.') +param permission string + +// ============== // +// Resources // +// ============== // + +resource namespace 'Microsoft.EventGrid/namespaces@2023-12-15-preview' existing = { + name: namespaceName +} + +resource permissionBinding 'Microsoft.EventGrid/namespaces/permissionBindings@2023-12-15-preview' = { + name: name + parent: namespace + properties: { + clientGroupName: clientGroupName + description: description + permission: permission + topicSpaceName: topicSpaceName + } +} + +// ============ // +// Outputs // +// ============ // + +@sys.description('The resource ID of the Permission Binding.') +output resourceId string = permissionBinding.id + +@sys.description('The name of the Permission Binding.') +output name string = permissionBinding.name + +@sys.description('The name of the resource group the Permission Binding was created in.') +output resourceGroupName string = resourceGroup().name + +// ================ // +// Definitions // +// ================ // +// +// Add your User-defined-types here, if any +// diff --git a/avm/res/event-grid/namespace/permission-binding/main.json b/avm/res/event-grid/namespace/permission-binding/main.json new file mode 100644 index 0000000000..066199c338 --- /dev/null +++ b/avm/res/event-grid/namespace/permission-binding/main.json @@ -0,0 +1,103 @@ +{ + "$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": "5622068529761827218" + }, + "name": "Eventgrid Namespace Permissions Bindings", + "description": "This module deploys an Eventgrid Namespace Permission Binding.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "namespaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Permission Binding." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Description of the Permission Binding." + } + }, + "clientGroupName": { + "type": "string", + "metadata": { + "description": "Required. The name of the client group resource that the permission is bound to. The client group needs to be a resource under the same namespace the permission binding is a part of." + } + }, + "topicSpaceName": { + "type": "string", + "metadata": { + "description": "Required. The name of the Topic Space resource that the permission is bound to. The Topic space needs to be a resource under the same namespace the permission binding is a part of." + } + }, + "permission": { + "type": "string", + "allowedValues": [ + "Publisher", + "Subscriber" + ], + "metadata": { + "description": "Required. The allowed permission." + } + } + }, + "resources": { + "namespace": { + "existing": true, + "type": "Microsoft.EventGrid/namespaces", + "apiVersion": "2023-12-15-preview", + "name": "[parameters('namespaceName')]" + }, + "permissionBinding": { + "type": "Microsoft.EventGrid/namespaces/permissionBindings", + "apiVersion": "2023-12-15-preview", + "name": "[format('{0}/{1}', parameters('namespaceName'), parameters('name'))]", + "properties": { + "clientGroupName": "[parameters('clientGroupName')]", + "description": "[parameters('description')]", + "permission": "[parameters('permission')]", + "topicSpaceName": "[parameters('topicSpaceName')]" + }, + "dependsOn": [ + "namespace" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Permission Binding." + }, + "value": "[resourceId('Microsoft.EventGrid/namespaces/permissionBindings', parameters('namespaceName'), parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the Permission Binding." + }, + "value": "[parameters('name')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the Permission Binding was created in." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/event-grid/namespace/tests/e2e/defaults/main.test.bicep b/avm/res/event-grid/namespace/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..b616ea7110 --- /dev/null +++ b/avm/res/event-grid/namespace/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,46 @@ +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}-eventgrid.namespace-${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 = 'egnmin' + +@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 + } +}] diff --git a/avm/res/event-grid/namespace/tests/e2e/max/dependencies.bicep b/avm/res/event-grid/namespace/tests/e2e/max/dependencies.bicep new file mode 100644 index 0000000000..f2d9cb0e70 --- /dev/null +++ b/avm/res/event-grid/namespace/tests/e2e/max/dependencies.bicep @@ -0,0 +1,102 @@ +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +@description('Required. The name of the Event Hub Namespace to create.') +param eventHubNamespaceName string + +@description('Required. The name of the Event Hub to create.') +param eventHubName string + +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) + } + } + ] + } +} + +resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { + name: 'privatelink.eventgrid.azure.net' + location: 'global' + + resource virtualNetworkLinks 'virtualNetworkLinks@2020-06-01' = { + name: '${virtualNetwork.name}-vnetlink' + location: 'global' + properties: { + virtualNetwork: { + id: virtualNetwork.id + } + registrationEnabled: false + } + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource eventHubNamespace 'Microsoft.EventHub/namespaces@2022-10-01-preview' = { + name: eventHubNamespaceName + location: location + properties: { + zoneRedundant: false + isAutoInflateEnabled: false + maximumThroughputUnits: 0 + } + + resource eventHub 'eventhubs@2022-10-01-preview' = { + name: eventHubName + } +} + +resource eventHubNamespaceRbacAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(managedIdentity.id, 'evhrbacAssignment') + scope: eventHubNamespace + properties: { + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2b629674-e913-4c01-ae53-ef4638d8f975') // Azure Event Hubs Data Sender + principalId: managedIdentity.properties.principalId + principalType: 'ServicePrincipal' + } +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].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 + +@description('The resource ID of the created Private DNS Zone.') +output privateDNSZoneResourceId string = privateDNSZone.id + +@description('The name of the Event Hub Namespace.') +output eventhubNamespaceName string = eventHubNamespace.name + +@description('The resource ID of the created Event Hub Namespace.') +output eventHubResourceId string = eventHubNamespace::eventHub.id + +@description('The name of the Event Hub.') +output eventhubName string = eventHubNamespace::eventHub.name diff --git a/avm/res/event-grid/namespace/tests/e2e/max/main.test.bicep b/avm/res/event-grid/namespace/tests/e2e/max/main.test.bicep new file mode 100644 index 0000000000..69d432f2a6 --- /dev/null +++ b/avm/res/event-grid/namespace/tests/e2e/max/main.test.bicep @@ -0,0 +1,244 @@ +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}-eventgrid.namespace-${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 = 'egnmax' + +@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: { + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + eventHubName: 'dep-${namePrefix}-evh-${serviceShort}' + eventHubNamespaceName: 'dep-${namePrefix}-evhns-${serviceShort}' + location: resourceLocation + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-diagnosticDependencies' + params: { + storageAccountName: 'dep${namePrefix}diasa${serviceShort}01' + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-${uniqueString(serviceShort, namePrefix)}-evh-01' + eventHubNamespaceName: 'dep-${uniqueString(serviceShort, namePrefix)}-evh-01' + 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 + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + privateEndpoints: [ + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + } + ] + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + topics: [ + { + name: 'topic1' + eventRetentionInDays: 7 + eventSubscriptions: [ + { + name: 'subscription1' + 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' + } + ] + deliveryConfiguration: { + deliveryMode: 'Queue' + queue: { + receiveLockDurationInSeconds: 60 + maxDeliveryCount: 10 + eventTimeToLive: 'P7D' + } + } + } + { + name: 'subscription2' + deliveryConfiguration: { + deliveryMode: 'Push' + push: { + maxDeliveryCount: 10 + eventTimeToLive: 'P7D' + deliveryWithResourceIdentity: { + identity: { + type: 'UserAssigned' + userAssignedIdentity: nestedDependencies.outputs.managedIdentityResourceId + } + destination: { + endpointType: 'EventHub' + properties: { + resourceId: nestedDependencies.outputs.eventHubResourceId + deliveryAttributeMappings: [ + { + properties: { + value: 'staticVaule' + isSecret: false + } + name: 'StaticHeader1' + type: 'Static' + } + { + properties: { + sourceField: 'id' + } + name: 'DynamicHeader1' + type: 'Dynamic' + } + { + properties: { + value: 'Hidden' + isSecret: true + } + name: 'StaticSecretHeader1' + type: 'Static' + } + ] + } + } + } + } + } + } + ] + } + { + name: 'topic2' + 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' + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + } + ] + } +}] diff --git a/avm/res/event-grid/namespace/tests/e2e/mqttct/dependencies.bicep b/avm/res/event-grid/namespace/tests/e2e/mqttct/dependencies.bicep new file mode 100644 index 0000000000..d3c4a66d2a --- /dev/null +++ b/avm/res/event-grid/namespace/tests/e2e/mqttct/dependencies.bicep @@ -0,0 +1,41 @@ +@description('Optional. The location to deploy resources 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 Event Grid Topic to create.') +param eventGridTopicName string + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource eventGridTopic 'Microsoft.EventGrid/topics@2023-12-15-preview' = { + name: eventGridTopicName + location: location + properties: { + minimumTlsVersionAllowed: '1.2' + inputSchema: 'CloudEventSchemaV1_0' + } +} + +resource eventGridTopicRbacAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(managedIdentity.id, 'evgtRbacAssignment') + scope: eventGridTopic + properties: { + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7') // EventGrid Data Sender + principalId: managedIdentity.properties.principalId + principalType: 'ServicePrincipal' + } +} + +@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 + +@description('The resource ID of the created Event Grid Topic.') +output eventGridTopicResourceId string = eventGridTopic.id diff --git a/avm/res/event-grid/namespace/tests/e2e/mqttct/main.test.bicep b/avm/res/event-grid/namespace/tests/e2e/mqttct/main.test.bicep new file mode 100644 index 0000000000..382a608544 --- /dev/null +++ b/avm/res/event-grid/namespace/tests/e2e/mqttct/main.test.bicep @@ -0,0 +1,194 @@ +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.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-eventgrid.namespace-${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 = 'egnmqttct' + +@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: { + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + eventGridTopicName: 'dep-${namePrefix}-evgt-${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 + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + topics: [ + { + name: 'topic1' + } + ] + topicSpacesState: 'Enabled' + maximumClientSessionsPerAuthenticationName: 5 + maximumSessionExpiryInHours: 2 + routeTopicResourceId: nestedDependencies.outputs.eventGridTopicResourceId + routingIdentityInfo: { + type: 'UserAssigned' + userAssignedIdentity: nestedDependencies.outputs.managedIdentityResourceId + } + routingEnrichments: { + static: [ + { + key: 'static1' + value: 'value1' + valueType: 'String' + } + { + key: 'static2' + value: 'value2' + valueType: 'String' + } + ] + dynamic: [ + { + key: 'dynamic1' + value: '\${client.authenticationName}' + } + ] + } + alternativeAuthenticationNameSources: [ + 'ClientCertificateEmail' + 'ClientCertificateUri' + ] + // caCertificates: [ + // { + // name: 'exampleCert' + // encodedCertificate: ''' + // ''' + // } + // ] + clients: [ + { + name: 'client1' + authenticationName: 'client2auth' + description: 'this is client2' + clientCertificateAuthenticationValidationSchema: 'ThumbprintMatch' + clientCertificateAuthenticationAllowedThumbprints: [ + '1111111111111111111111111111111111111111' + '2222222222222222222222222222222222222222' + ] + state: 'Enabled' + attributes: { + room: '345' + floor: 12 + deviceTypes: [ + 'Fan' + 'Light' + ] + } + } + { + name: 'client2' + clientCertificateAuthenticationValidationSchema: 'ThumbprintMatch' + clientCertificateAuthenticationAllowedThumbprints: [ + '3333333333333333333333333333333333333333' + ] + } + { + name: 'client3' + } + { + name: 'client4' + clientCertificateAuthenticationValidationSchema: 'IpMatchesAuthenticationName' + } + ] + clientGroups: [ + { + name: 'group1' + query: 'attributes.keyName IN [\'a\', \'b\', \'c\']' + description: 'this is group1' + } + ] + topicSpaces: [ + { + name: 'topicSpace1' + topicTemplates: [ + 'devices/foo/bar' + 'devices/topic1/+' + ] + } + { + name: 'topicSpace2' + topicTemplates: [ + 'devices/topic1/+' + ] + 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' + } + ] + } + ] + permissionBindings: [ + { + name: 'bindiing1' + description: 'this is binding1' + clientGroupName: 'group1' + topicSpaceName: 'topicSpace1' + permission: 'Publisher' + } + { + name: 'bindiing2' + clientGroupName: 'group1' + topicSpaceName: 'topicSpace2' + permission: 'Subscriber' + } + ] + } +}] diff --git a/avm/res/event-grid/namespace/tests/e2e/mqttnt/dependencies.bicep b/avm/res/event-grid/namespace/tests/e2e/mqttnt/dependencies.bicep new file mode 100644 index 0000000000..0e36a0607f --- /dev/null +++ b/avm/res/event-grid/namespace/tests/e2e/mqttnt/dependencies.bicep @@ -0,0 +1,37 @@ +@description('Optional. The location to deploy resources 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 EventGrid Namespace to create.') +param eventGridNamespaceName string + +@description('Required. The name of the EventGrid Namespace Topic to create.') +param eventGridNamespaceTopicName string + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { + name: managedIdentityName + location: location +} + +resource eventGridNamespace 'Microsoft.EventGrid/namespaces@2023-12-15-preview' = { + name: eventGridNamespaceName + location: location + + resource topic 'topics@2023-12-15-preview' = { + name: eventGridNamespaceTopicName + properties: { + inputSchema: 'CloudEventSchemaV1_0' + } + } +} + +@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 + +@description('The resource Id of the created EventGrid Namespace Topic.') +output eventGridNameSpaceTopicResourceId string = eventGridNamespace::topic.id 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 new file mode 100644 index 0000000000..40265c3ba5 --- /dev/null +++ b/avm/res/event-grid/namespace/tests/e2e/mqttnt/main.test.bicep @@ -0,0 +1,195 @@ +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.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-eventgrid.namespace-${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 = 'egnmqttnt' + +@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: { + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + eventGridNamespaceName: '${namePrefix}${serviceShort}001' + eventGridNamespaceTopicName: 'topic1' + 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 + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + topics: [ + { + name: 'topic1' + } + ] + topicSpacesState: 'Enabled' + maximumClientSessionsPerAuthenticationName: 5 + maximumSessionExpiryInHours: 2 + routeTopicResourceId: nestedDependencies.outputs.eventGridNameSpaceTopicResourceId + routingIdentityInfo: { + type: 'UserAssigned' + userAssignedIdentity: nestedDependencies.outputs.managedIdentityResourceId + } + routingEnrichments: { + static: [ + { + key: 'static1' + value: 'value1' + valueType: 'String' + } + { + key: 'static2' + value: 'value2' + valueType: 'String' + } + ] + dynamic: [ + { + key: 'dynamic1' + value: '\${client.authenticationName}' + } + ] + } + alternativeAuthenticationNameSources: [ + 'ClientCertificateEmail' + 'ClientCertificateUri' + ] + // caCertificates: [ + // { + // name: 'exampleCert' + // encodedCertificate: ''' + // ''' + // } + // ] + clients: [ + { + name: 'client1' + authenticationName: 'client2auth' + description: 'this is client2' + clientCertificateAuthenticationValidationSchema: 'ThumbprintMatch' + clientCertificateAuthenticationAllowedThumbprints: [ + '1111111111111111111111111111111111111111' + '2222222222222222222222222222222222222222' + ] + state: 'Enabled' + attributes: { + room: '345' + floor: 12 + deviceTypes: [ + 'Fan' + 'Light' + ] + } + } + { + name: 'client2' + clientCertificateAuthenticationValidationSchema: 'ThumbprintMatch' + clientCertificateAuthenticationAllowedThumbprints: [ + '3333333333333333333333333333333333333333' + ] + } + { + name: 'client3' + } + { + name: 'client4' + clientCertificateAuthenticationValidationSchema: 'IpMatchesAuthenticationName' + } + ] + clientGroups: [ + { + name: 'group1' + query: 'attributes.keyName IN [\'a\', \'b\', \'c\']' + description: 'this is group1' + } + ] + topicSpaces: [ + { + name: 'topicSpace1' + topicTemplates: [ + 'devices/foo/bar' + 'devices/topic1/+' + ] + } + { + name: 'topicSpace2' + topicTemplates: [ + 'devices/topic1/+' + ] + 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' + } + ] + } + ] + permissionBindings: [ + { + name: 'bindiing1' + description: 'this is binding1' + clientGroupName: 'group1' + topicSpaceName: 'topicSpace1' + permission: 'Publisher' + } + { + name: 'bindiing2' + clientGroupName: 'group1' + topicSpaceName: 'topicSpace2' + permission: 'Subscriber' + } + ] + } +}] diff --git a/avm/res/event-grid/namespace/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/event-grid/namespace/tests/e2e/waf-aligned/dependencies.bicep new file mode 100644 index 0000000000..4131d043ae --- /dev/null +++ b/avm/res/event-grid/namespace/tests/e2e/waf-aligned/dependencies.bicep @@ -0,0 +1,63 @@ +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +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) + } + } + ] + } +} + +resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { + name: 'privatelink.eventgrid.azure.net' + location: 'global' + + resource virtualNetworkLinks 'virtualNetworkLinks@2020-06-01' = { + name: '${virtualNetwork.name}-vnetlink' + location: 'global' + properties: { + virtualNetwork: { + id: virtualNetwork.id + } + registrationEnabled: false + } + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].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 + +@description('The resource ID of the created Private DNS Zone.') +output privateDNSZoneResourceId string = privateDNSZone.id diff --git a/avm/res/event-grid/namespace/tests/e2e/waf-aligned/main.test.bicep b/avm/res/event-grid/namespace/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..62eef80089 --- /dev/null +++ b/avm/res/event-grid/namespace/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,119 @@ +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}-eventgrid.namespace-${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 = 'egnwaf' + +@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: { + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: resourceLocation + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-diagnosticDependencies' + params: { + storageAccountName: 'dep${namePrefix}diasa${serviceShort}01' + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-${uniqueString(serviceShort, namePrefix)}-evh-01' + eventHubNamespaceName: 'dep-${uniqueString(serviceShort, namePrefix)}-evh-01' + 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 + diagnosticSettings: [ + { + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + privateEndpoints: [ + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + } + ] + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/event-grid/namespace/topic-space/README.md b/avm/res/event-grid/namespace/topic-space/README.md new file mode 100644 index 0000000000..4fc1929791 --- /dev/null +++ b/avm/res/event-grid/namespace/topic-space/README.md @@ -0,0 +1,174 @@ +# Eventgrid Namespace Topic Spaces `[Microsoft.EventGrid/namespaces/topicSpaces]` + +This module deploys an Eventgrid Namespace Topic Space. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| 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.EventGrid/namespaces/topicSpaces` | [2023-12-15-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.EventGrid/2023-12-15-preview/namespaces/topicSpaces) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the Topic Space. | +| [`topicTemplates`](#parameter-topictemplates) | array | The topic filters in the Topic Space. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`namespaceName`](#parameter-namespacename) | string | The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`description`](#parameter-description) | string | Description of the Topic Space. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | + +### Parameter: `name` + +Name of the Topic Space. + +- Required: Yes +- Type: string + +### Parameter: `topicTemplates` + +The topic filters in the Topic Space. + +- Required: Yes +- Type: array + +### Parameter: `namespaceName` + +The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `description` + +Description of the Topic Space. + +- Required: No +- Type: string + +### Parameter: `roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**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. | +| [`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.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Topic Space. | +| `resourceGroupName` | string | The name of the resource group the Topic Space was created in. | +| `resourceId` | string | The resource ID of the Topic Space. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/event-grid/namespace/topic-space/main.bicep b/avm/res/event-grid/namespace/topic-space/main.bicep new file mode 100644 index 0000000000..f3e9e4e149 --- /dev/null +++ b/avm/res/event-grid/namespace/topic-space/main.bicep @@ -0,0 +1,106 @@ +metadata name = 'Eventgrid Namespace Topic Spaces' +metadata description = 'This module deploys an Eventgrid Namespace Topic Space.' +metadata owner = 'Azure/module-maintainers' + +@sys.description('Conditional. The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment.') +param namespaceName string + +@sys.description('Required. Name of the Topic Space.') +param name string + +@sys.description('Optional. Description of the Topic Space.') +param description string? + +@minLength(1) +@sys.description('Required. The topic filters in the Topic Space.') +param topicTemplates array + +@sys.description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +var builtInRoleNames = { + 'Azure Resource Notifications System Topics Subscriber': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0b962ed2-6d56-471c-bd5f-3477d83a7ba4') + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'EventGrid Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1e241071-0855-49ea-94dc-649edcd759de') + 'EventGrid Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d8c3fe3-8864-474b-8749-01e3783e8157') + 'EventGrid Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '78cbd9e7-9798-4e2e-9b5a-547d9ebb31fb') + 'EventGrid Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7') + 'EventGrid EventSubscription Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443') + 'EventGrid EventSubscription Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405') + 'EventGrid TopicSpaces Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a12b0b94-b317-4dcd-84a8-502ce99884c6') + 'EventGrid TopicSpaces Subscriber': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4b0f2fd7-60b4-4eca-896f-4435034f8bf5') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +// ============== // +// Resources // +// ============== // + +resource namespace 'Microsoft.EventGrid/namespaces@2023-12-15-preview' existing = { + name: namespaceName +} + +resource topicSpace 'Microsoft.EventGrid/namespaces/topicSpaces@2023-12-15-preview' = { + name: name + parent: namespace + properties: { + description: description + topicTemplates: topicTemplates + } +} + +resource topic_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(topicSpace.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: topicSpace +}] + +// ============ // +// Outputs // +// ============ // + +@sys.description('The resource ID of the Topic Space.') +output resourceId string = topicSpace.id + +@sys.description('The name of the Topic Space.') +output name string = topicSpace.name + +@sys.description('The name of the resource group the Topic Space was created in.') +output resourceGroupName string = resourceGroup().name + +// ================ // +// Definitions // +// ================ // + +type roleAssignmentType = { + @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/event-grid/namespace/topic-space/main.json b/avm/res/event-grid/namespace/topic-space/main.json new file mode 100644 index 0000000000..f094351427 --- /dev/null +++ b/avm/res/event-grid/namespace/topic-space/main.json @@ -0,0 +1,199 @@ +{ + "$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": "6548696237893842735" + }, + "name": "Eventgrid Namespace Topic Spaces", + "description": "This module deploys an Eventgrid Namespace Topic Space.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "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": { + "namespaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Topic Space." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Description of the Topic Space." + } + }, + "topicTemplates": { + "type": "array", + "minLength": 1, + "metadata": { + "description": "Required. The topic filters in the Topic Space." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "builtInRoleNames": { + "Azure Resource Notifications System Topics Subscriber": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0b962ed2-6d56-471c-bd5f-3477d83a7ba4')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "EventGrid Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1e241071-0855-49ea-94dc-649edcd759de')]", + "EventGrid Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d8c3fe3-8864-474b-8749-01e3783e8157')]", + "EventGrid Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '78cbd9e7-9798-4e2e-9b5a-547d9ebb31fb')]", + "EventGrid Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7')]", + "EventGrid EventSubscription Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443')]", + "EventGrid EventSubscription Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405')]", + "EventGrid TopicSpaces Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a12b0b94-b317-4dcd-84a8-502ce99884c6')]", + "EventGrid TopicSpaces Subscriber": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4b0f2fd7-60b4-4eca-896f-4435034f8bf5')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "namespace": { + "existing": true, + "type": "Microsoft.EventGrid/namespaces", + "apiVersion": "2023-12-15-preview", + "name": "[parameters('namespaceName')]" + }, + "topicSpace": { + "type": "Microsoft.EventGrid/namespaces/topicSpaces", + "apiVersion": "2023-12-15-preview", + "name": "[format('{0}/{1}', parameters('namespaceName'), parameters('name'))]", + "properties": { + "description": "[parameters('description')]", + "topicTemplates": "[parameters('topicTemplates')]" + }, + "dependsOn": [ + "namespace" + ] + }, + "topic_roleAssignments": { + "copy": { + "name": "topic_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.EventGrid/namespaces/{0}/topicSpaces/{1}', parameters('namespaceName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.EventGrid/namespaces/topicSpaces', parameters('namespaceName'), 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": [ + "topicSpace" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Topic Space." + }, + "value": "[resourceId('Microsoft.EventGrid/namespaces/topicSpaces', parameters('namespaceName'), parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the Topic Space." + }, + "value": "[parameters('name')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the Topic Space was created in." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/event-grid/namespace/topic/README.md b/avm/res/event-grid/namespace/topic/README.md new file mode 100644 index 0000000000..234d969644 --- /dev/null +++ b/avm/res/event-grid/namespace/topic/README.md @@ -0,0 +1,232 @@ +# Eventgrid Namespace Topics `[Microsoft.EventGrid/namespaces/topics]` + +This module deploys an Eventgrid Namespace Topic. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [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.EventGrid/namespaces/topics` | [2023-12-15-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.EventGrid/2023-12-15-preview/namespaces/topics) | +| `Microsoft.EventGrid/namespaces/topics/eventSubscriptions` | [2023-12-15-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.EventGrid/2023-12-15-preview/namespaces/topics/eventSubscriptions) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the topic. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`namespaceName`](#parameter-namespacename) | string | The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`eventRetentionInDays`](#parameter-eventretentionindays) | int | Event retention for the namespace topic expressed in days. | +| [`eventSubscriptions`](#parameter-eventsubscriptions) | array | All event subscriptions to create. | +| [`inputSchema`](#parameter-inputschema) | string | This determines the format that is expected for incoming events published to the topic. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`publisherType`](#parameter-publishertype) | string | Publisher type of the namespace topic. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | + +### Parameter: `name` + +Name of the topic. + +- Required: Yes +- Type: string + +### Parameter: `namespaceName` + +The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `eventRetentionInDays` + +Event retention for the namespace topic expressed in days. + +- Required: No +- Type: int +- Default: `1` + +### Parameter: `eventSubscriptions` + +All event subscriptions to create. + +- Required: No +- Type: array + +### Parameter: `inputSchema` + +This determines the format that is expected for incoming events published to the topic. + +- Required: No +- Type: string +- Default: `'CloudEventSchemaV1_0'` + +### 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: `publisherType` + +Publisher type of the namespace topic. + +- Required: No +- Type: string +- Default: `'Custom'` + +### Parameter: `roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**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. | +| [`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.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Namespace Topic. | +| `resourceGroupName` | string | The name of the resource group the Namespace Topic was created in. | +| `resourceId` | string | The resource ID of the Namespace Topic. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/event-grid/namespace/topic/event-subscription/README.md b/avm/res/event-grid/namespace/topic/event-subscription/README.md new file mode 100644 index 0000000000..9bedd147ad --- /dev/null +++ b/avm/res/event-grid/namespace/topic/event-subscription/README.md @@ -0,0 +1,191 @@ +# Event Subscriptions `[Microsoft.EventGrid/namespaces/topics/eventSubscriptions]` + +This module deploys an Event Subscription. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| 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.EventGrid/namespaces/topics/eventSubscriptions` | [2023-12-15-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.EventGrid/2023-12-15-preview/namespaces/topics/eventSubscriptions) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the Event Subscription to create. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`namespaceName`](#parameter-namespacename) | string | The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment. | +| [`topicName`](#parameter-topicname) | string | The name of the parent EventGrid namespace topic. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`deliveryConfiguration`](#parameter-deliveryconfiguration) | object | Information about the delivery configuration of the Event Subscription. | +| [`eventDeliverySchema`](#parameter-eventdeliveryschema) | string | The event delivery schema for the Event Subscription. | +| [`filtersConfiguration`](#parameter-filtersconfiguration) | object | Information about the filter for the Event Subscription. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | + +### Parameter: `name` + +Name of the Event Subscription to create. + +- Required: Yes +- Type: string + +### Parameter: `namespaceName` + +The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `topicName` + +The name of the parent EventGrid namespace topic. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `deliveryConfiguration` + +Information about the delivery configuration of the Event Subscription. + +- Required: No +- Type: object + +### Parameter: `eventDeliverySchema` + +The event delivery schema for the Event Subscription. + +- Required: No +- Type: string +- Default: `'CloudEventSchemaV1_0'` + +### Parameter: `filtersConfiguration` + +Information about the filter for the Event Subscription. + +- Required: No +- Type: object + +### Parameter: `roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**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. | +| [`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.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Event Subscription. | +| `resourceGroupName` | string | The name of the resource group the Event Subscription was created in. | +| `resourceId` | string | The resource ID of the Event Subscription. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/event-grid/namespace/topic/event-subscription/main.bicep b/avm/res/event-grid/namespace/topic/event-subscription/main.bicep new file mode 100644 index 0000000000..f8d8c63bfc --- /dev/null +++ b/avm/res/event-grid/namespace/topic/event-subscription/main.bicep @@ -0,0 +1,118 @@ +metadata name = 'Event Subscriptions' +metadata description = 'This module deploys an Event Subscription.' +metadata owner = 'Azure/module-maintainers' + +@description('Conditional. The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment.') +param namespaceName string + +@description('Conditional. The name of the parent EventGrid namespace topic. Required if the template is used in a standalone deployment.') +param topicName string + +@description('Required. Name of the Event Subscription to create.') +param name string + +@description('Optional. Information about the delivery configuration of the Event Subscription.') +param deliveryConfiguration object? + +@description('Optional. The event delivery schema for the Event Subscription.') +param eventDeliverySchema string = 'CloudEventSchemaV1_0' + +@description('Optional. Information about the filter for the Event Subscription.') +param filtersConfiguration object? + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +var builtInRoleNames = { + 'Azure Resource Notifications System Topics Subscriber': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0b962ed2-6d56-471c-bd5f-3477d83a7ba4') + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'EventGrid Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1e241071-0855-49ea-94dc-649edcd759de') + 'EventGrid Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d8c3fe3-8864-474b-8749-01e3783e8157') + 'EventGrid Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '78cbd9e7-9798-4e2e-9b5a-547d9ebb31fb') + 'EventGrid Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7') + 'EventGrid EventSubscription Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443') + 'EventGrid EventSubscription Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405') + 'EventGrid TopicSpaces Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a12b0b94-b317-4dcd-84a8-502ce99884c6') + 'EventGrid TopicSpaces Subscriber': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4b0f2fd7-60b4-4eca-896f-4435034f8bf5') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +// ============== // +// Resources // +// ============== // + +resource namespace 'Microsoft.EventGrid/namespaces@2023-12-15-preview' existing = { + name: namespaceName + + resource topic 'topics@2023-12-15-preview' existing = { + name: topicName + } +} + +resource eventSubscription 'Microsoft.EventGrid/namespaces/topics/eventSubscriptions@2023-12-15-preview' = { + name: name + parent: namespace::topic + properties: { + deliveryConfiguration: deliveryConfiguration + eventDeliverySchema: eventDeliverySchema + filtersConfiguration: filtersConfiguration + } +} + +resource eventSubscription_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(eventSubscription.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: eventSubscription +}] + +// ============ // +// Outputs // +// ============ // + +// Add your outputs here + +@description('The resource ID of the Event Subscription.') +output resourceId string = eventSubscription.id + +@description('The name of the Event Subscription.') +output name string = eventSubscription.name + +@description('The name of the resource group the Event Subscription was created in.') +output resourceGroupName string = resourceGroup().name + +// ================ // +// Definitions // +// ================ // + +type roleAssignmentType = { + @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/event-grid/namespace/topic/event-subscription/main.json b/avm/res/event-grid/namespace/topic/event-subscription/main.json new file mode 100644 index 0000000000..6895d512f1 --- /dev/null +++ b/avm/res/event-grid/namespace/topic/event-subscription/main.json @@ -0,0 +1,222 @@ +{ + "$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": "13130499975324434363" + }, + "name": "Event Subscriptions", + "description": "This module deploys an Event Subscription.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "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": { + "namespaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment." + } + }, + "topicName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent EventGrid namespace topic. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Event Subscription to create." + } + }, + "deliveryConfiguration": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Information about the delivery configuration of the Event Subscription." + } + }, + "eventDeliverySchema": { + "type": "string", + "defaultValue": "CloudEventSchemaV1_0", + "metadata": { + "description": "Optional. The event delivery schema for the Event Subscription." + } + }, + "filtersConfiguration": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Information about the filter for the Event Subscription." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "builtInRoleNames": { + "Azure Resource Notifications System Topics Subscriber": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0b962ed2-6d56-471c-bd5f-3477d83a7ba4')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "EventGrid Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1e241071-0855-49ea-94dc-649edcd759de')]", + "EventGrid Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d8c3fe3-8864-474b-8749-01e3783e8157')]", + "EventGrid Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '78cbd9e7-9798-4e2e-9b5a-547d9ebb31fb')]", + "EventGrid Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7')]", + "EventGrid EventSubscription Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443')]", + "EventGrid EventSubscription Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405')]", + "EventGrid TopicSpaces Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a12b0b94-b317-4dcd-84a8-502ce99884c6')]", + "EventGrid TopicSpaces Subscriber": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4b0f2fd7-60b4-4eca-896f-4435034f8bf5')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "namespace::topic": { + "existing": true, + "type": "Microsoft.EventGrid/namespaces/topics", + "apiVersion": "2023-12-15-preview", + "name": "[format('{0}/{1}', parameters('namespaceName'), parameters('topicName'))]", + "dependsOn": [ + "namespace" + ] + }, + "namespace": { + "existing": true, + "type": "Microsoft.EventGrid/namespaces", + "apiVersion": "2023-12-15-preview", + "name": "[parameters('namespaceName')]" + }, + "eventSubscription": { + "type": "Microsoft.EventGrid/namespaces/topics/eventSubscriptions", + "apiVersion": "2023-12-15-preview", + "name": "[format('{0}/{1}/{2}', parameters('namespaceName'), parameters('topicName'), parameters('name'))]", + "properties": { + "deliveryConfiguration": "[parameters('deliveryConfiguration')]", + "eventDeliverySchema": "[parameters('eventDeliverySchema')]", + "filtersConfiguration": "[parameters('filtersConfiguration')]" + }, + "dependsOn": [ + "namespace::topic" + ] + }, + "eventSubscription_roleAssignments": { + "copy": { + "name": "eventSubscription_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.EventGrid/namespaces/{0}/topics/{1}/eventSubscriptions/{2}', parameters('namespaceName'), parameters('topicName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.EventGrid/namespaces/topics/eventSubscriptions', parameters('namespaceName'), parameters('topicName'), 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": [ + "eventSubscription" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Event Subscription." + }, + "value": "[resourceId('Microsoft.EventGrid/namespaces/topics/eventSubscriptions', parameters('namespaceName'), parameters('topicName'), parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the Event Subscription." + }, + "value": "[parameters('name')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the Event Subscription was created in." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/event-grid/namespace/topic/main.bicep b/avm/res/event-grid/namespace/topic/main.bicep new file mode 100644 index 0000000000..9bc8a5fe64 --- /dev/null +++ b/avm/res/event-grid/namespace/topic/main.bicep @@ -0,0 +1,147 @@ +metadata name = 'Eventgrid Namespace Topics' +metadata description = 'This module deploys an Eventgrid Namespace Topic.' +metadata owner = 'Azure/module-maintainers' + +@description('Conditional. The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment.') +param namespaceName string + +@description('Required. Name of the topic.') +param name string + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +@description('Optional. The lock settings of the service.') +param lock lockType + +@minValue(1) +@maxValue(7) +@description('Optional. Event retention for the namespace topic expressed in days.') +param eventRetentionInDays int = 1 + +@description('Optional. This determines the format that is expected for incoming events published to the topic.') +param inputSchema string = 'CloudEventSchemaV1_0' + +@description('Optional. Publisher type of the namespace topic.') +param publisherType string = 'Custom' + +@description('Optional. All event subscriptions to create.') +param eventSubscriptions array? + +var builtInRoleNames = { + 'Azure Resource Notifications System Topics Subscriber': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0b962ed2-6d56-471c-bd5f-3477d83a7ba4') + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'EventGrid Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1e241071-0855-49ea-94dc-649edcd759de') + 'EventGrid Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d8c3fe3-8864-474b-8749-01e3783e8157') + 'EventGrid Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '78cbd9e7-9798-4e2e-9b5a-547d9ebb31fb') + 'EventGrid Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7') + 'EventGrid EventSubscription Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443') + 'EventGrid EventSubscription Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405') + 'EventGrid TopicSpaces Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a12b0b94-b317-4dcd-84a8-502ce99884c6') + 'EventGrid TopicSpaces Subscriber': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4b0f2fd7-60b4-4eca-896f-4435034f8bf5') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +// ============== // +// Resources // +// ============== // + +resource namespace 'Microsoft.EventGrid/namespaces@2023-12-15-preview' existing = { + name: namespaceName +} + +resource topic 'Microsoft.EventGrid/namespaces/topics@2023-12-15-preview' = { + name: name + parent: namespace + properties: { + eventRetentionInDays: eventRetentionInDays + inputSchema: inputSchema + publisherType: publisherType + } +} + +resource topic_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: topic +} + +resource topic_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(topic.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: topic +}] + +module topic_eventSubscriptions 'event-subscription/main.bicep' = [for (eventSubscription, index) in (eventSubscriptions ?? []): { + name: '${uniqueString(deployment().name, topic.name)}-Topic-EventSubscription-${index}' + params: { + name: eventSubscription.name + namespaceName: namespace.name + topicName: topic.name + deliveryConfiguration: eventSubscription.?deliveryConfiguration + eventDeliverySchema: eventSubscription.?eventDeliverySchema + filtersConfiguration: eventSubscription.?filtersConfiguration + roleAssignments: eventSubscription.?roleAssignments + } +}] + +// ============ // +// Outputs // +// ============ // + +@description('The resource ID of the Namespace Topic.') +output resourceId string = topic.id + +@description('The name of the Namespace Topic.') +output name string = topic.name + +@description('The name of the resource group the Namespace Topic was created in.') +output resourceGroupName string = resourceGroup().name + +// ================ // +// 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('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/event-grid/namespace/topic/main.json b/avm/res/event-grid/namespace/topic/main.json new file mode 100644 index 0000000000..60a89a526b --- /dev/null +++ b/avm/res/event-grid/namespace/topic/main.json @@ -0,0 +1,525 @@ +{ + "$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": "2836208779363789051" + }, + "name": "Eventgrid Namespace Topics", + "description": "This module deploys an Eventgrid Namespace Topic.", + "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": { + "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": { + "namespaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the topic." + } + }, + "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." + } + }, + "eventRetentionInDays": { + "type": "int", + "defaultValue": 1, + "minValue": 1, + "maxValue": 7, + "metadata": { + "description": "Optional. Event retention for the namespace topic expressed in days." + } + }, + "inputSchema": { + "type": "string", + "defaultValue": "CloudEventSchemaV1_0", + "metadata": { + "description": "Optional. This determines the format that is expected for incoming events published to the topic." + } + }, + "publisherType": { + "type": "string", + "defaultValue": "Custom", + "metadata": { + "description": "Optional. Publisher type of the namespace topic." + } + }, + "eventSubscriptions": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. All event subscriptions to create." + } + } + }, + "variables": { + "builtInRoleNames": { + "Azure Resource Notifications System Topics Subscriber": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0b962ed2-6d56-471c-bd5f-3477d83a7ba4')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "EventGrid Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1e241071-0855-49ea-94dc-649edcd759de')]", + "EventGrid Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d8c3fe3-8864-474b-8749-01e3783e8157')]", + "EventGrid Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '78cbd9e7-9798-4e2e-9b5a-547d9ebb31fb')]", + "EventGrid Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7')]", + "EventGrid EventSubscription Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443')]", + "EventGrid EventSubscription Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405')]", + "EventGrid TopicSpaces Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a12b0b94-b317-4dcd-84a8-502ce99884c6')]", + "EventGrid TopicSpaces Subscriber": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4b0f2fd7-60b4-4eca-896f-4435034f8bf5')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "namespace": { + "existing": true, + "type": "Microsoft.EventGrid/namespaces", + "apiVersion": "2023-12-15-preview", + "name": "[parameters('namespaceName')]" + }, + "topic": { + "type": "Microsoft.EventGrid/namespaces/topics", + "apiVersion": "2023-12-15-preview", + "name": "[format('{0}/{1}', parameters('namespaceName'), parameters('name'))]", + "properties": { + "eventRetentionInDays": "[parameters('eventRetentionInDays')]", + "inputSchema": "[parameters('inputSchema')]", + "publisherType": "[parameters('publisherType')]" + }, + "dependsOn": [ + "namespace" + ] + }, + "topic_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.EventGrid/namespaces/{0}/topics/{1}', parameters('namespaceName'), 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": [ + "topic" + ] + }, + "topic_roleAssignments": { + "copy": { + "name": "topic_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.EventGrid/namespaces/{0}/topics/{1}', parameters('namespaceName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.EventGrid/namespaces/topics', parameters('namespaceName'), 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": [ + "topic" + ] + }, + "topic_eventSubscriptions": { + "copy": { + "name": "topic_eventSubscriptions", + "count": "[length(coalesce(parameters('eventSubscriptions'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Topic-EventSubscription-{1}', uniqueString(deployment().name, parameters('name')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(parameters('eventSubscriptions'), createArray())[copyIndex()].name]" + }, + "namespaceName": { + "value": "[parameters('namespaceName')]" + }, + "topicName": { + "value": "[parameters('name')]" + }, + "deliveryConfiguration": { + "value": "[tryGet(coalesce(parameters('eventSubscriptions'), createArray())[copyIndex()], 'deliveryConfiguration')]" + }, + "eventDeliverySchema": { + "value": "[tryGet(coalesce(parameters('eventSubscriptions'), createArray())[copyIndex()], 'eventDeliverySchema')]" + }, + "filtersConfiguration": { + "value": "[tryGet(coalesce(parameters('eventSubscriptions'), createArray())[copyIndex()], 'filtersConfiguration')]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('eventSubscriptions'), 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.25.53.49325", + "templateHash": "13130499975324434363" + }, + "name": "Event Subscriptions", + "description": "This module deploys an Event Subscription.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "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": { + "namespaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent EventGrid namespace. Required if the template is used in a standalone deployment." + } + }, + "topicName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent EventGrid namespace topic. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Event Subscription to create." + } + }, + "deliveryConfiguration": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Information about the delivery configuration of the Event Subscription." + } + }, + "eventDeliverySchema": { + "type": "string", + "defaultValue": "CloudEventSchemaV1_0", + "metadata": { + "description": "Optional. The event delivery schema for the Event Subscription." + } + }, + "filtersConfiguration": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Information about the filter for the Event Subscription." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "builtInRoleNames": { + "Azure Resource Notifications System Topics Subscriber": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0b962ed2-6d56-471c-bd5f-3477d83a7ba4')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "EventGrid Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1e241071-0855-49ea-94dc-649edcd759de')]", + "EventGrid Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d8c3fe3-8864-474b-8749-01e3783e8157')]", + "EventGrid Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '78cbd9e7-9798-4e2e-9b5a-547d9ebb31fb')]", + "EventGrid Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7')]", + "EventGrid EventSubscription Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443')]", + "EventGrid EventSubscription Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405')]", + "EventGrid TopicSpaces Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a12b0b94-b317-4dcd-84a8-502ce99884c6')]", + "EventGrid TopicSpaces Subscriber": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4b0f2fd7-60b4-4eca-896f-4435034f8bf5')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "namespace::topic": { + "existing": true, + "type": "Microsoft.EventGrid/namespaces/topics", + "apiVersion": "2023-12-15-preview", + "name": "[format('{0}/{1}', parameters('namespaceName'), parameters('topicName'))]", + "dependsOn": [ + "namespace" + ] + }, + "namespace": { + "existing": true, + "type": "Microsoft.EventGrid/namespaces", + "apiVersion": "2023-12-15-preview", + "name": "[parameters('namespaceName')]" + }, + "eventSubscription": { + "type": "Microsoft.EventGrid/namespaces/topics/eventSubscriptions", + "apiVersion": "2023-12-15-preview", + "name": "[format('{0}/{1}/{2}', parameters('namespaceName'), parameters('topicName'), parameters('name'))]", + "properties": { + "deliveryConfiguration": "[parameters('deliveryConfiguration')]", + "eventDeliverySchema": "[parameters('eventDeliverySchema')]", + "filtersConfiguration": "[parameters('filtersConfiguration')]" + }, + "dependsOn": [ + "namespace::topic" + ] + }, + "eventSubscription_roleAssignments": { + "copy": { + "name": "eventSubscription_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.EventGrid/namespaces/{0}/topics/{1}/eventSubscriptions/{2}', parameters('namespaceName'), parameters('topicName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.EventGrid/namespaces/topics/eventSubscriptions', parameters('namespaceName'), parameters('topicName'), 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": [ + "eventSubscription" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Event Subscription." + }, + "value": "[resourceId('Microsoft.EventGrid/namespaces/topics/eventSubscriptions', parameters('namespaceName'), parameters('topicName'), parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the Event Subscription." + }, + "value": "[parameters('name')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the Event Subscription was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "namespace", + "topic" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Namespace Topic." + }, + "value": "[resourceId('Microsoft.EventGrid/namespaces/topics', parameters('namespaceName'), parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the Namespace Topic." + }, + "value": "[parameters('name')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the Namespace Topic was created in." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/event-grid/namespace/version.json b/avm/res/event-grid/namespace/version.json new file mode 100644 index 0000000000..8def869ede --- /dev/null +++ b/avm/res/event-grid/namespace/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.1", + "pathFilters": [ + "./main.json" + ] +} From f36615b5894cf3b614d9cd7537ac683eb43a65b2 Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Thu, 14 Mar 2024 19:58:28 +0000 Subject: [PATCH 32/73] feat: Added workflow for syncing CSV labels to GitHub Labels (#1285) **Test Run:** https://github.com/jtracey93/bicep-registry-modules/actions/runs/8285523952/job/22673465780 This pull request introduces a new GitHub Actions workflow in the `.github/workflows/avm.platform.sync-repo-labels-from-csv.yml` file. The workflow is designed to synchronize labels from a CSV file to GitHub labels. It is scheduled to run daily at 3:45 AM PST and can also be manually triggered. The workflow runs on an Ubuntu-latest environment and uses a PowerShell script to perform the synchronization. Key changes include: * New GitHub Actions workflow: A new workflow named `avm.platform.sync-repo-labels-from-csv` has been added. This workflow is set to run on a schedule and can also be manually triggered. * Concurrency settings: The workflow is configured to allow only one concurrent deployment. If a new deployment is triggered while another one is in progress, the in-progress deployment will be cancelled. * Permissions: The workflow has write permissions for issues and pull requests. * Workflow job: The workflow contains a job named `sync-labels` that runs on an `ubuntu-latest` environment. The job uses a PowerShell script to synchronize labels from a CSV file to GitHub labels. --- ...avm.platform.sync-repo-labels-from-csv.yml | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/workflows/avm.platform.sync-repo-labels-from-csv.yml diff --git a/.github/workflows/avm.platform.sync-repo-labels-from-csv.yml b/.github/workflows/avm.platform.sync-repo-labels-from-csv.yml new file mode 100644 index 0000000000..d33fb79970 --- /dev/null +++ b/.github/workflows/avm.platform.sync-repo-labels-from-csv.yml @@ -0,0 +1,31 @@ +# Workflow for syncing CSV labels to GitHub Labels +name: avm.platform.sync-repo-labels-from-csv + +on: + schedule: + - cron: 45 11 * * * # Run daily at 3:45 AM PST + workflow_dispatch: {} + +# Allow one concurrent deployment +concurrency: + group: "labels" + cancel-in-progress: true + +permissions: + issues: write + pull-requests: write + +defaults: + run: + shell: pwsh + +jobs: + sync-labels: + runs-on: ubuntu-latest + steps: + - name: Sync AVM Labels To Repos GitHub Labels + run: | + Invoke-WebRequest -Uri "https://raw.githubusercontent.com/Azure/Azure-Verified-Modules/main/docs/static/scripts/Set-AvmGitHubLabels.ps1" -OutFile "./Set-AvmGitHubLabels.ps1" + ./Set-AvmGitHubLabels.ps1 -RepositoryName "${{ github.repository }}" -CreateCsvLabelExports $false -RemoveExistingLabels $false -NoUserPrompts $true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From f8f81019782aadb63a4d842f18782fa65835e068 Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Fri, 15 Mar 2024 16:50:55 +0000 Subject: [PATCH 33/73] feat: Add PSRule analysis for WAF Reliability Pillar for module defaults - V2 (#1263) ## Description Add PSRule analysis for WAF Reliability Pillar for module defaults ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.analysis-services.server](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.analysis-services.server.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.analysis-services.server.yml) [![avm.res.api-management.service](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.api-management.service.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.api-management.service.yml) [![avm.res.app-configuration.configuration-store](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.app-configuration.configuration-store.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.app-configuration.configuration-store.yml) [![avm.res.app.container-app](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.app.container-app.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.app.container-app.yml) [![avm.res.app.managed-environment](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.app.managed-environment.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.app.managed-environment.yml) [![avm.res.automation.automation-account](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.automation.automation-account.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.automation.automation-account.yml) [![avm.res.batch.batch-account](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.batch.batch-account.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.batch.batch-account.yml) [![avm.res.cache.redis](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.cache.redis.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.cache.redis.yml) [![avm.res.cdn.profile](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.cdn.profile.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.cdn.profile.yml) [![avm.res.cognitive-services.account](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.cognitive-services.account.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.cognitive-services.account.yml) [![avm.res.compute.availability-set](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.compute.availability-set.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.compute.availability-set.yml) [![avm.res.compute.disk-encryption-set](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.compute.disk-encryption-set.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.compute.disk-encryption-set.yml) [![avm.res.compute.disk](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.compute.disk.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.compute.disk.yml) [![avm.res.compute.gallery](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.compute.gallery.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.compute.gallery.yml) [![avm.res.compute.image](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.compute.image.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.compute.image.yml) [![avm.res.compute.proximity-placement-group](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.compute.proximity-placement-group.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.compute.proximity-placement-group.yml) [![avm.res.compute.ssh-public-key](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.compute.ssh-public-key.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.compute.ssh-public-key.yml) [![avm.res.compute.virtual-machine-scale-set](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.compute.virtual-machine-scale-set.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.compute.virtual-machine-scale-set.yml) [![avm.res.compute.virtual-machine](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.compute.virtual-machine.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.compute.virtual-machine.yml) [![avm.res.consumption.budget](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.consumption.budget.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.consumption.budget.yml) [![avm.res.container-registry.registry](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.container-registry.registry.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.container-registry.registry.yml) [![avm.res.container-service.managed-cluster](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.container-service.managed-cluster.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.container-service.managed-cluster.yml) [![avm.res.data-factory.factory](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.data-factory.factory.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.data-factory.factory.yml) [![avm.res.data-protection.backup-vault](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.data-protection.backup-vault.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.data-protection.backup-vault.yml) [![avm.res.databricks.access-connector](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.databricks.access-connector.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.databricks.access-connector.yml) [![avm.res.databricks.workspace](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.databricks.workspace.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.databricks.workspace.yml) [![avm.res.db-for-my-sql.flexible-server](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.db-for-my-sql.flexible-server.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.db-for-my-sql.flexible-server.yml) [![avm.res.db-for-postgre-sql.flexible-server](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.db-for-postgre-sql.flexible-server.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.db-for-postgre-sql.flexible-server.yml) [![avm.res.desktop-virtualization.application-group](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.desktop-virtualization.application-group.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.desktop-virtualization.application-group.yml) [![avm.res.desktop-virtualization.host-pool](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.desktop-virtualization.host-pool.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.desktop-virtualization.host-pool.yml) [![avm.res.desktop-virtualization.scaling-plan](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.desktop-virtualization.scaling-plan.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.desktop-virtualization.scaling-plan.yml) [![avm.res.desktop-virtualization.workspace](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.desktop-virtualization.workspace.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.desktop-virtualization.workspace.yml) [![avm.res.dev-test-lab.lab](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.dev-test-lab.lab.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.dev-test-lab.lab.yml) [![avm.res.document-db.database-account](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.document-db.database-account.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.document-db.database-account.yml) [![avm.res.event-grid.domain](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.event-grid.domain.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.event-grid.domain.yml) [![avm.res.event-grid.namespace](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.event-grid.namespace.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.event-grid.namespace.yml) [![avm.res.event-grid.system-topic](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.event-grid.system-topic.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.event-grid.system-topic.yml) [![avm.res.event-grid.topic](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.event-grid.topic.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.event-grid.topic.yml) [![avm.res.event-hub.namespace](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.event-hub.namespace.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.event-hub.namespace.yml) [![avm.res.health-bot.health-bot](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.health-bot.health-bot.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.health-bot.health-bot.yml) [![avm.res.insights.action-group](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.insights.action-group.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.insights.action-group.yml) [![avm.res.insights.activity-log-alert](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.insights.activity-log-alert.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.insights.activity-log-alert.yml) [![avm.res.insights.component](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.insights.component.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.insights.component.yml) [![avm.res.insights.data-collection-endpoint](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.insights.data-collection-endpoint.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.insights.data-collection-endpoint.yml) [![avm.res.insights.data-collection-rule](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.insights.data-collection-rule.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.insights.data-collection-rule.yml) [![avm.res.insights.diagnostic-setting](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.insights.diagnostic-setting.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.insights.diagnostic-setting.yml) [![avm.res.insights.metric-alert](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.insights.metric-alert.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.insights.metric-alert.yml) [![avm.res.insights.private-link-scope](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.insights.private-link-scope.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.insights.private-link-scope.yml) [![avm.res.insights.scheduled-query-rule](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.insights.scheduled-query-rule.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.insights.scheduled-query-rule.yml) [![avm.res.insights.webtest](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.insights.webtest.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.insights.webtest.yml) [![avm.res.key-vault.vault](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.key-vault.vault.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.key-vault.vault.yml) [![avm.res.kubernetes-configuration.extension](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.kubernetes-configuration.extension.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.kubernetes-configuration.extension.yml) [![avm.res.kubernetes-configuration.flux-configuration](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.kubernetes-configuration.flux-configuration.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.kubernetes-configuration.flux-configuration.yml) [![avm.res.logic.workflow](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.logic.workflow.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.logic.workflow.yml) [![avm.res.machine-learning-services.workspace](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.machine-learning-services.workspace.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.machine-learning-services.workspace.yml) [![avm.res.maintenance.maintenance-configuration](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.maintenance.maintenance-configuration.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.maintenance.maintenance-configuration.yml) [![avm.res.managed-identity.user-assigned-identity](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.managed-identity.user-assigned-identity.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.managed-identity.user-assigned-identity.yml) [![avm.res.management.management-group](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.management.management-group.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.management.management-group.yml) [![avm.res.net-app.net-app-account](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.net-app.net-app-account.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.net-app.net-app-account.yml) [![avm.res.network.application-security-group](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.application-security-group.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.application-security-group.yml) [![avm.res.network.azure-firewall](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.azure-firewall.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.azure-firewall.yml) [![avm.res.network.bastion-host](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.bastion-host.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.bastion-host.yml) [![avm.res.network.connection](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.connection.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.connection.yml) [![avm.res.network.ddos-protection-plan](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.ddos-protection-plan.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.ddos-protection-plan.yml) [![avm.res.network.dns-forwarding-ruleset](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.dns-forwarding-ruleset.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.dns-forwarding-ruleset.yml) [![avm.res.network.dns-resolver](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.dns-resolver.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.dns-resolver.yml) [![avm.res.network.dns-zone](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.dns-zone.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.dns-zone.yml) [![avm.res.network.express-route-circuit](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.express-route-circuit.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.express-route-circuit.yml) [![avm.res.network.express-route-gateway](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.express-route-gateway.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.express-route-gateway.yml) [![avm.res.network.firewall-policy](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.firewall-policy.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.firewall-policy.yml) [![avm.res.network.front-door-web-application-firewall-policy](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.front-door-web-application-firewall-policy.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.front-door-web-application-firewall-policy.yml) [![avm.res.network.front-door](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.front-door.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.front-door.yml) [![avm.res.network.ip-group](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.ip-group.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.ip-group.yml) [![avm.res.network.load-balancer](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.load-balancer.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.load-balancer.yml) [![avm.res.network.local-network-gateway](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.local-network-gateway.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.local-network-gateway.yml) [![avm.res.network.nat-gateways](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.nat-gateway.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.nat-gateway.yml) [![avm.res.network.network-interface](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.network-interface.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.network-interface.yml) [![avm.res.network.network-manager](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.network-manager.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.network-manager.yml) [![avm.res.network.network-security-group](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.network-security-group.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.network-security-group.yml) [![avm.res.network.private-dns-zone](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.private-dns-zone.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.private-dns-zone.yml) [![avm.res.network.private-endpoint](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.private-endpoint.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.private-endpoint.yml) [![avm.res.network.private-link-service](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.private-link-service.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.private-link-service.yml) [![avm.res.network.public-ip-address](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.public-ip-address.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.public-ip-address.yml) [![avm.res.network.public-ip-prefix](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.public-ip-prefix.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.public-ip-prefix.yml) [![avm.res.network.route-table](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.route-table.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.route-table.yml) [![avm.res.network.trafficmanagerprofile](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.trafficmanagerprofile.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.trafficmanagerprofile.yml) [![avm.res.network.virtual-hub](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.virtual-hub.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.virtual-hub.yml) [![avm.res.network.virtual-network-gateway](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.virtual-network-gateway.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.virtual-network-gateway.yml) [![avm.res.network.virtual-network](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.virtual-network.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.virtual-network.yml) [![avm.res.network.virtual-wan](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.virtual-wan.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.virtual-wan.yml) [![avm.res.network.vpn-gateway](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.vpn-gateway.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.vpn-gateway.yml) [![avm.res.network.vpn-site](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.vpn-site.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.vpn-site.yml) [![avm.res.operational-insights.workspace](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.operational-insights.workspace.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.operational-insights.workspace.yml) [![avm.res.operations-management.solution](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.operations-management.solution.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.operations-management.solution.yml) [![avm.res.power-bi-dedicated.capacity](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.power-bi-dedicated.capacity.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.power-bi-dedicated.capacity.yml) [![avm.res.purview.account](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.purview.account.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.purview.account.yml) [![avm.res.resource-graph.query](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.resource-graph.query.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.resource-graph.query.yml) [![avm.res.resources.deployment-script](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.resources.deployment-script.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.resources.deployment-script.yml) [![avm.res.resources.resource-group](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.resources.resource-group.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.resources.resource-group.yml) [![avm.res.search.search-service](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.search.search-service.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.search.search-service.yml) [![avm.res.service-bus.namespace](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.service-bus.namespace.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.service-bus.namespace.yml) [![avm.res.signal-r-service.signal-r](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.signal-r-service.signal-r.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.signal-r-service.signal-r.yml) [![avm.res.signal-r-service.web-pub-sub](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.signal-r-service.web-pub-sub.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.signal-r-service.web-pub-sub.yml) [![avm.res.sql.server](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.sql.server.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.sql.server.yml) [![avm.res.storage.storage-account](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.storage.storage-account.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.storage.storage-account.yml) [![avm.res.synapse.private-link-hub](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.synapse.private-link-hub.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.synapse.private-link-hub.yml) [![avm.res.synapse.workspace](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.synapse.workspace.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.synapse.workspace.yml) [![avm.res.virtual-machine-images.image-template](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.virtual-machine-images.image-template.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.virtual-machine-images.image-template.yml) [![avm.res.web.serverfarm](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.web.serverfarm.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.web.serverfarm.yml) [![avm.res.web.site](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.web.site.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.web.site.yml) [![avm.res.web.static-site](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.web.static-site.yml/badge.svg?branch=feat%2Fadd-waf-reliability-tests-v2&event=workflow_dispatch)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.web.static-site.yml) | ## Type of Change - [x] Update to CI Environment or utlities (Non-module effecting changes) - [ ] Azure Verified Module updates: - [ ] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [ ] I have run `Set-AVMModule` locally to generate the supporting module files. - [x] My corresponding pipelines / checks run clean and green without any errors or warnings --------- Co-authored-by: Erika Gressi <56914614+eriqua@users.noreply.github.com> --- .../avm-validateModulePSRule/action.yml | 24 +++++++++++++++-- .github/workflows/avm.template.module.yml | 26 ++++++++++++++++++- .../staticValidation/psrule/ps-rule.yaml | 4 +-- 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/.github/actions/templates/avm-validateModulePSRule/action.yml b/.github/actions/templates/avm-validateModulePSRule/action.yml index ad44068a7e..6cc60d4b67 100644 --- a/.github/actions/templates/avm-validateModulePSRule/action.yml +++ b/.github/actions/templates/avm-validateModulePSRule/action.yml @@ -37,6 +37,10 @@ inputs: psrulePath: description: "The path to PSRule configurations" required: false + psruleBaseline: + description: "The PSRule baseline to be used" + required: true + default: "Azure.Default" runs: using: "composite" @@ -109,11 +113,27 @@ runs: # [PSRule validation] task(s) #----------------------------- - - name: Run PSRule analysis + - name: Run PSRule analysis - All Pillars (Azure.Default) + uses: microsoft/ps-rule@v2.9.0 + if: ${{ inputs.psruleBaseline == 'Azure.Default' }} + continue-on-error: true + with: + modules: "PSRule.Rules.Azure" + 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 - Reliability Pillar Only (Azure.Pillar.Reliability) uses: microsoft/ps-rule@v2.9.0 - continue-on-error: true # Setting this whilst PSRule gets bedded in, in this project + if: ${{ inputs.psruleBaseline == 'Azure.Pillar.Reliability' }} with: modules: "PSRule.Rules.Azure" + prerelease: true + baseline: "${{ inputs.psruleBaseline }}" inputPath: "${{ inputs.templateFilePath}}" outputFormat: Csv outputPath: "${{ inputs.templateFilePath}}-PSRule-output.csv" diff --git a/.github/workflows/avm.template.module.yml b/.github/workflows/avm.template.module.yml index 48fe6ab9f6..a87e0c1596 100644 --- a/.github/workflows/avm.template.module.yml +++ b/.github/workflows/avm.template.module.yml @@ -69,6 +69,29 @@ jobs: subscriptionId: "${{ secrets.ARM_SUBSCRIPTION_ID }}" managementGroupId: "${{ secrets.ARM_MGMTGROUP_ID }}" psrulePath: "avm/utilities/pipelines/staticValidation/psrule" #'${{ github.workspace }}/avm' + psruleBaseline: "Azure.Default" + + job_psrule_test_waf_reliability: # 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 Reliability [${{ matrix.testCases.name }}]" + runs-on: ubuntu-latest + if: (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.Reliability" ############################# # Deployment validation # @@ -78,9 +101,10 @@ jobs: runs-on: ubuntu-latest if: | !cancelled() && - (fromJson(inputs.workflowInput)).deploymentValidation == 'true' && needs.job_module_static_validation.result != 'failure' + (fromJson(inputs.workflowInput)).deploymentValidation == 'true' && needs.job_module_static_validation.result != 'failure' && needs.job_psrule_test_waf_reliability != 'failure' needs: - job_module_static_validation + - job_psrule_test_waf_reliability strategy: fail-fast: false matrix: diff --git a/avm/utilities/pipelines/staticValidation/psrule/ps-rule.yaml b/avm/utilities/pipelines/staticValidation/psrule/ps-rule.yaml index a0664f4949..d6ced73afb 100644 --- a/avm/utilities/pipelines/staticValidation/psrule/ps-rule.yaml +++ b/avm/utilities/pipelines/staticValidation/psrule/ps-rule.yaml @@ -16,7 +16,7 @@ binding: # Require minimum versions of modules. requires: PSRule: "@pre >=2.9.0" - PSRule.Rules.Azure: ">=1.29.0" + PSRule.Rules.Azure: "@pre >=1.29.0" # Use PSRule for Azure. include: @@ -68,7 +68,7 @@ configuration: "tokenname", "ssoClientSecretKeyVaultPath", "ssoSecretType", - "tokenValidityLength" + "tokenValidityLength", ] rule: From 15605e8d2accb2d1241eb2ce0ce1e94af35d061b Mon Sep 17 00:00:00 2001 From: Alexander Sehr Date: Sun, 17 Mar 2024 03:08:54 -0400 Subject: [PATCH 34/73] fix: Updated MSI Web Site output to convention (#1246) ## Description Updated MSI Web Site output to convention ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.web.site](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.web.site.yml/badge.svg?branch=users%2Falsehr%2FmsiOutput_slot&event=workflow_dispatch)](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.web.site.yml) | --- avm/res/web/site/config--appsettings/main.json | 2 +- avm/res/web/site/main.bicep | 2 +- avm/res/web/site/main.json | 12 ++++++------ avm/res/web/site/slot/config--appsettings/main.json | 2 +- avm/res/web/site/slot/main.bicep | 2 +- avm/res/web/site/slot/main.json | 6 +++--- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/avm/res/web/site/config--appsettings/main.json b/avm/res/web/site/config--appsettings/main.json index 9e9b315c7b..67706c0b50 100644 --- a/avm/res/web/site/config--appsettings/main.json +++ b/avm/res/web/site/config--appsettings/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "9880720466726925484" + "templateHash": "1933221834367063613" }, "name": "Site App Settings", "description": "This module deploys a Site App Setting.", diff --git a/avm/res/web/site/main.bicep b/avm/res/web/site/main.bicep index e9067b63c2..8de8ff1d99 100644 --- a/avm/res/web/site/main.bicep +++ b/avm/res/web/site/main.bicep @@ -420,7 +420,7 @@ output slotResourceIds array = [for (slot, index) in (slots ?? []): app_slots[in output resourceGroupName string = resourceGroup().name @description('The principal ID of the system assigned identity.') -output systemAssignedMIPrincipalId string = (managedIdentities.?systemAssigned ?? false) && contains(app.identity, 'principalId') ? app.identity.principalId : '' +output systemAssignedMIPrincipalId string = app.?identity.?principalId ?? '' @description('The principal ID of the system assigned identity of slots.') output slotSystemAssignedMIPrincipalIds array = [for (slot, index) in (slots ?? []): app_slots[index].outputs.systemAssignedMIPrincipalId] diff --git a/avm/res/web/site/main.json b/avm/res/web/site/main.json index 33c06c27a5..dc3cf78d44 100644 --- a/avm/res/web/site/main.json +++ b/avm/res/web/site/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "7010125481271494880" + "templateHash": "13529659123294184484" }, "name": "Web/Function Apps", "description": "This module deploys a Web or Function App.", @@ -927,7 +927,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "9880720466726925484" + "templateHash": "1933221834367063613" }, "name": "Site App Settings", "description": "This module deploys a Site App Setting.", @@ -1296,7 +1296,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "7766866613475753287" + "templateHash": "11139469624723604210" }, "name": "Web/Function App Deployment Slots", "description": "This module deploys a Web or Function App Deployment Slot.", @@ -2201,7 +2201,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "10338815995098199032" + "templateHash": "10996922119937137063" }, "name": "Site Slot App Settings", "description": "This module deploys a Site Slot App Setting.", @@ -3381,7 +3381,7 @@ "metadata": { "description": "The principal ID of the system assigned identity." }, - "value": "[if(and(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), contains(reference('slot', '2022-09-01', 'full').identity, 'principalId')), reference('slot', '2022-09-01', 'full').identity.principalId, '')]" + "value": "[coalesce(tryGet(tryGet(reference('slot', '2022-09-01', 'full'), 'identity'), 'principalId'), '')]" }, "location": { "type": "string", @@ -4329,7 +4329,7 @@ "metadata": { "description": "The principal ID of the system assigned identity." }, - "value": "[if(and(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), contains(reference('app', '2022-09-01', 'full').identity, 'principalId')), reference('app', '2022-09-01', 'full').identity.principalId, '')]" + "value": "[coalesce(tryGet(tryGet(reference('app', '2022-09-01', 'full'), 'identity'), 'principalId'), '')]" }, "slotSystemAssignedMIPrincipalIds": { "type": "array", diff --git a/avm/res/web/site/slot/config--appsettings/main.json b/avm/res/web/site/slot/config--appsettings/main.json index 6bcec10463..4c6ed30b38 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.25.53.49325", - "templateHash": "10338815995098199032" + "templateHash": "10996922119937137063" }, "name": "Site Slot App Settings", "description": "This module deploys a Site Slot App Setting.", diff --git a/avm/res/web/site/slot/main.bicep b/avm/res/web/site/slot/main.bicep index f0c0740a69..1ba45eb733 100644 --- a/avm/res/web/site/slot/main.bicep +++ b/avm/res/web/site/slot/main.bicep @@ -347,7 +347,7 @@ output resourceId string = slot.id output resourceGroupName string = resourceGroup().name @description('The principal ID of the system assigned identity.') -output systemAssignedMIPrincipalId string = (managedIdentities.?systemAssigned ?? false) && contains(slot.identity, 'principalId') ? slot.identity.principalId : '' +output systemAssignedMIPrincipalId string = slot.?identity.?principalId ?? '' @description('The location the resource was deployed into.') output location string = slot.location diff --git a/avm/res/web/site/slot/main.json b/avm/res/web/site/slot/main.json index 3213bd8cd8..811f9db83c 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.25.53.49325", - "templateHash": "7766866613475753287" + "templateHash": "11139469624723604210" }, "name": "Web/Function App Deployment Slots", "description": "This module deploys a Web or Function App Deployment Slot.", @@ -911,7 +911,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "10338815995098199032" + "templateHash": "10996922119937137063" }, "name": "Site Slot App Settings", "description": "This module deploys a Site Slot App Setting.", @@ -2091,7 +2091,7 @@ "metadata": { "description": "The principal ID of the system assigned identity." }, - "value": "[if(and(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), contains(reference('slot', '2022-09-01', 'full').identity, 'principalId')), reference('slot', '2022-09-01', 'full').identity.principalId, '')]" + "value": "[coalesce(tryGet(tryGet(reference('slot', '2022-09-01', 'full'), 'identity'), 'principalId'), '')]" }, "location": { "type": "string", From a43967bf0eaa65853f05cf2d3e69785805bcffde Mon Sep 17 00:00:00 2001 From: Erika Gressi <56914614+eriqua@users.noreply.github.com> Date: Sun, 17 Mar 2024 12:44:50 +0000 Subject: [PATCH 35/73] fix: Skip deployment if PSRule WAF reliability validation fails (#1311) ## Description Update reusable workflow validation template to correctly skip deployment validation if the newly introduced PSRule WAF reliability check fails ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.network.bastion-host](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.network.bastion-host.yml/badge.svg?branch=eriqua-patch-1)](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.network.bastion-host.yml) (As intended, skips deployment after PSRule reliability check failure) | ## Type of Change - [x] Update to CI Environment or utlities (Non-module effecting changes) - [ ] Azure Verified Module updates: - [ ] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [ ] I have run `Set-AVMModule` locally to generate the supporting module files. - [ ] My corresponding pipelines / checks run clean and green without any errors or warnings --- .github/workflows/avm.template.module.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/avm.template.module.yml b/.github/workflows/avm.template.module.yml index a87e0c1596..5d8ea22141 100644 --- a/.github/workflows/avm.template.module.yml +++ b/.github/workflows/avm.template.module.yml @@ -101,7 +101,7 @@ jobs: runs-on: ubuntu-latest if: | !cancelled() && - (fromJson(inputs.workflowInput)).deploymentValidation == 'true' && needs.job_module_static_validation.result != 'failure' && needs.job_psrule_test_waf_reliability != 'failure' + (fromJson(inputs.workflowInput)).deploymentValidation == 'true' && needs.job_module_static_validation.result != 'failure' && needs.job_psrule_test_waf_reliability.result != 'failure' needs: - job_module_static_validation - job_psrule_test_waf_reliability From d5e213ff748eacf97cf9961d8cad7262093a711a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Mar 2024 09:36:16 +0000 Subject: [PATCH 36/73] chore(deps-dev): bump follow-redirects from 1.15.4 to 1.15.6 (#1287) Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.4 to 1.15.6.

Commits
  • 35a517c Release version 1.15.6 of the npm package.
  • c4f847f Drop Proxy-Authorization across hosts.
  • 8526b4a Use GitHub for disclosure.
  • b1677ce Release version 1.15.5 of the npm package.
  • d8914f7 Preserve fragment in responseUrl.
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=follow-redirects&package-manager=npm_and_yarn&previous-version=1.15.4&new-version=1.15.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/Azure/bicep-registry-modules/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index cd483773f3..0747b32820 100644 --- a/package-lock.json +++ b/package-lock.json @@ -681,9 +681,9 @@ "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", - "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "dev": true, "funding": [ { @@ -1871,9 +1871,9 @@ "dev": true }, "follow-redirects": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", - "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "dev": true }, "form-data": { From ada06bbb0a57a445ff54f907a7b0825c3ec9a1ef Mon Sep 17 00:00:00 2001 From: Alexander Sehr Date: Mon, 18 Mar 2024 09:18:58 -0400 Subject: [PATCH 37/73] fix: Corrected vanity link for RBAC UDT (#1320) ## Description Corrected vanity link for RBAC UDT ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.analysis-services.server](https://github.com/AlexanderSehr/bicep-registry-modules/actions/workflows/avm.res.analysis-services.server.yml/badge.svg?branch=users%2Falsehr%2FrbacUdtLinkFix&event=workflow_dispatch)](https://github.com/AlexanderSehr/bicep-registry-modules/actions/workflows/avm.res.analysis-services.server.yml) | --------- Co-authored-by: Erika Gressi <56914614+eriqua@users.noreply.github.com> --- .../pipelines/staticValidation/compliance/module.tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 index 108904bed5..4880560c0c 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 @@ -639,7 +639,7 @@ Describe 'Module tests' -Tag 'Module' { @{ parameterName = 'roleAssignments' udtName = 'roleAssignmentType' - udtExpectedUrl = "$interfaceBase/diagnostic-settings/udt-schema" + udtExpectedUrl = "$interfaceBase/role-assignments/udt-schema" link = "$interfaceBase/role-assignments" } @{ From c4af2c6b4348ce384b5b3e94d3224738c67be7dc Mon Sep 17 00:00:00 2001 From: Kris Baranek Date: Tue, 19 Mar 2024 08:47:06 +0100 Subject: [PATCH 38/73] fix: unorphaned `avm/res/cdn/profile` (#1325) ## Description Unorphaned `avm/res/cdn/profile` module as @gbeaud recently became the owner of this module. ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.cdn.profile](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.cdn.profile.yml/badge.svg?branch=users%2Fkrbar%2FunorphanCDN)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.cdn.profile.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [x] Azure Verified Module updates: - [x] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [x] I have run `Set-AVMModule` locally to generate the supporting module files. - [x] My corresponding pipelines / checks run clean and green without any errors or warnings --- avm/res/cdn/profile/ORPHANED.md | 4 ---- avm/res/cdn/profile/README.md | 5 ----- 2 files changed, 9 deletions(-) delete mode 100644 avm/res/cdn/profile/ORPHANED.md diff --git a/avm/res/cdn/profile/ORPHANED.md b/avm/res/cdn/profile/ORPHANED.md deleted file mode 100644 index ef8fa911d2..0000000000 --- a/avm/res/cdn/profile/ORPHANED.md +++ /dev/null @@ -1,4 +0,0 @@ -⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ - -- Only security and bug fixes are being handled by the AVM core team at present. -- If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! \ No newline at end of file diff --git a/avm/res/cdn/profile/README.md b/avm/res/cdn/profile/README.md index a1981f0781..39ea759b35 100644 --- a/avm/res/cdn/profile/README.md +++ b/avm/res/cdn/profile/README.md @@ -1,10 +1,5 @@ # CDN Profiles `[Microsoft.Cdn/profiles]` -> ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ -> -> - Only security and bug fixes are being handled by the AVM core team at present. -> - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! - This module deploys a CDN Profile. ## Navigation From 9647105c6e689669a229132626844cb00e6853af Mon Sep 17 00:00:00 2001 From: Erika Gressi <56914614+eriqua@users.noreply.github.com> Date: Tue, 19 Mar 2024 13:09:15 +0000 Subject: [PATCH 39/73] fix: Enable legacy formatter (#1331) ## Description Temporary enable legacy (v1) formatter via the `legacyFormatter` new feature flag. This is to ensure a smoother transition to the v2 formatter, made default by the latest bicep release 0.26.54. ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.storage.storage-account](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.storage.storage-account.yml/badge.svg?branch=feat%2Feriqua%2FlegacyFormatter)](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.storage.storage-account.yml) | ## Type of Change - [x] Update to CI Environment or utlities (Non-module effecting changes) - [ ] Azure Verified Module updates: - [ ] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [x] I have run `Set-AVMModule` locally to generate the supporting module files. - [ ] My corresponding pipelines / checks run clean and green without any errors or warnings --- avm/bicepconfig.json | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/avm/bicepconfig.json b/avm/bicepconfig.json index 24a40e0f6c..439facdc5b 100644 --- a/avm/bicepconfig.json +++ b/avm/bicepconfig.json @@ -1,10 +1,11 @@ // This is a Bicep configuration file. It can be used to control how Bicep operates and to customize validation settings for the Bicep linter. The linter uses these settings when evaluating your Bicep files for best practices. // For further information, please refer to the official documentation at: https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/bicep-config { - "experimentalFeaturesEnabled": { - "publishSource": true - }, - "analyzers": { + "experimentalFeaturesEnabled": { + "publishSource": true, + "legacyFormatter": true // Reason: Enables code formatting with the v1 formatter, ensuring a safer transition to the v2 formatter + }, + "analyzers": { "core": { "rules": { "no-deployments-resources": { @@ -13,4 +14,4 @@ } } } -} +} \ No newline at end of file From 308f4e3135ca90b26652a71ca9385ed4e0193e82 Mon Sep 17 00:00:00 2001 From: Erika Gressi <56914614+eriqua@users.noreply.github.com> Date: Tue, 19 Mar 2024 16:08:38 +0000 Subject: [PATCH 40/73] fix: Update module workflow triggers (#1294) ## Description Update module workflow triggers on push to exclude changes happening in folder `avm/utilities/pipelines/platform`. ## Pipeline Reference | Pipeline | | -------- | | N/A | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [ ] Azure Verified Module updates: - [ ] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [ ] I'm sure there are no other open Pull Requests for the same update/change - [ ] I have run `Set-AVMModule` locally to generate the supporting module files. - [ ] My corresponding pipelines / checks run clean and green without any errors or warnings --- .github/workflows/avm.res.analysis-services.server.yml | 1 + .github/workflows/avm.res.api-management.service.yml | 1 + .../workflows/avm.res.app-configuration.configuration-store.yml | 1 + .github/workflows/avm.res.app.container-app.yml | 1 + .github/workflows/avm.res.app.managed-environment.yml | 1 + .github/workflows/avm.res.automation.automation-account.yml | 1 + .github/workflows/avm.res.batch.batch-account.yml | 1 + .github/workflows/avm.res.cache.redis.yml | 1 + .github/workflows/avm.res.cdn.profile.yml | 1 + .github/workflows/avm.res.cognitive-services.account.yml | 1 + .github/workflows/avm.res.compute.availability-set.yml | 1 + .github/workflows/avm.res.compute.disk-encryption-set.yml | 1 + .github/workflows/avm.res.compute.disk.yml | 1 + .github/workflows/avm.res.compute.gallery.yml | 1 + .github/workflows/avm.res.compute.image.yml | 1 + .github/workflows/avm.res.compute.proximity-placement-group.yml | 1 + .github/workflows/avm.res.compute.ssh-public-key.yml | 1 + .github/workflows/avm.res.compute.virtual-machine-scale-set.yml | 1 + .github/workflows/avm.res.compute.virtual-machine.yml | 1 + .github/workflows/avm.res.consumption.budget.yml | 1 + .github/workflows/avm.res.container-registry.registry.yml | 1 + .github/workflows/avm.res.container-service.managed-cluster.yml | 1 + .github/workflows/avm.res.data-factory.factory.yml | 1 + .github/workflows/avm.res.data-protection.backup-vault.yml | 1 + .github/workflows/avm.res.databricks.access-connector.yml | 1 + .github/workflows/avm.res.databricks.workspace.yml | 1 + .github/workflows/avm.res.db-for-my-sql.flexible-server.yml | 1 + .github/workflows/avm.res.db-for-postgre-sql.flexible-server.yml | 1 + .../avm.res.desktop-virtualization.application-group.yml | 1 + .github/workflows/avm.res.desktop-virtualization.host-pool.yml | 1 + .../workflows/avm.res.desktop-virtualization.scaling-plan.yml | 1 + .github/workflows/avm.res.desktop-virtualization.workspace.yml | 1 + .github/workflows/avm.res.dev-test-lab.lab.yml | 1 + .github/workflows/avm.res.document-db.database-account.yml | 1 + .github/workflows/avm.res.event-grid.domain.yml | 1 + .github/workflows/avm.res.event-grid.namespace.yml | 1 + .github/workflows/avm.res.event-grid.system-topic.yml | 1 + .github/workflows/avm.res.event-grid.topic.yml | 1 + .github/workflows/avm.res.event-hub.namespace.yml | 1 + .github/workflows/avm.res.health-bot.health-bot.yml | 1 + .github/workflows/avm.res.insights.action-group.yml | 1 + .github/workflows/avm.res.insights.activity-log-alert.yml | 1 + .github/workflows/avm.res.insights.component.yml | 1 + .github/workflows/avm.res.insights.data-collection-endpoint.yml | 1 + .github/workflows/avm.res.insights.data-collection-rule.yml | 1 + .github/workflows/avm.res.insights.diagnostic-setting.yml | 1 + .github/workflows/avm.res.insights.metric-alert.yml | 1 + .github/workflows/avm.res.insights.private-link-scope.yml | 1 + .github/workflows/avm.res.insights.scheduled-query-rule.yml | 1 + .github/workflows/avm.res.insights.webtest.yml | 1 + .github/workflows/avm.res.key-vault.vault.yml | 1 + .github/workflows/avm.res.kubernetes-configuration.extension.yml | 1 + .../avm.res.kubernetes-configuration.flux-configuration.yml | 1 + .github/workflows/avm.res.logic.workflow.yml | 1 + .../workflows/avm.res.machine-learning-services.workspace.yml | 1 + .../workflows/avm.res.maintenance.maintenance-configuration.yml | 1 + .../avm.res.managed-identity.user-assigned-identity.yml | 1 + .github/workflows/avm.res.management.management-group.yml | 1 + .github/workflows/avm.res.net-app.net-app-account.yml | 1 + .github/workflows/avm.res.network.application-security-group.yml | 1 + .github/workflows/avm.res.network.azure-firewall.yml | 1 + .github/workflows/avm.res.network.bastion-host.yml | 1 + .github/workflows/avm.res.network.connection.yml | 1 + .github/workflows/avm.res.network.ddos-protection-plan.yml | 1 + .github/workflows/avm.res.network.dns-forwarding-ruleset.yml | 1 + .github/workflows/avm.res.network.dns-resolver.yml | 1 + .github/workflows/avm.res.network.dns-zone.yml | 1 + .github/workflows/avm.res.network.express-route-circuit.yml | 1 + .github/workflows/avm.res.network.express-route-gateway.yml | 1 + .github/workflows/avm.res.network.firewall-policy.yml | 1 + ...vm.res.network.front-door-web-application-firewall-policy.yml | 1 + .github/workflows/avm.res.network.front-door.yml | 1 + .github/workflows/avm.res.network.ip-group.yml | 1 + .github/workflows/avm.res.network.load-balancer.yml | 1 + .github/workflows/avm.res.network.local-network-gateway.yml | 1 + .github/workflows/avm.res.network.nat-gateway.yml | 1 + .github/workflows/avm.res.network.network-interface.yml | 1 + .github/workflows/avm.res.network.network-manager.yml | 1 + .github/workflows/avm.res.network.network-security-group.yml | 1 + .github/workflows/avm.res.network.private-dns-zone.yml | 1 + .github/workflows/avm.res.network.private-endpoint.yml | 1 + .github/workflows/avm.res.network.private-link-service.yml | 1 + .github/workflows/avm.res.network.public-ip-address.yml | 1 + .github/workflows/avm.res.network.public-ip-prefix.yml | 1 + .github/workflows/avm.res.network.route-table.yml | 1 + .github/workflows/avm.res.network.trafficmanagerprofile.yml | 1 + .github/workflows/avm.res.network.virtual-hub.yml | 1 + .github/workflows/avm.res.network.virtual-network-gateway.yml | 1 + .github/workflows/avm.res.network.virtual-network.yml | 1 + .github/workflows/avm.res.network.virtual-wan.yml | 1 + .github/workflows/avm.res.network.vpn-gateway.yml | 1 + .github/workflows/avm.res.network.vpn-site.yml | 1 + .github/workflows/avm.res.operational-insights.workspace.yml | 1 + .github/workflows/avm.res.operations-management.solution.yml | 1 + .github/workflows/avm.res.power-bi-dedicated.capacity.yml | 1 + .github/workflows/avm.res.purview.account.yml | 1 + .github/workflows/avm.res.resource-graph.query.yml | 1 + .github/workflows/avm.res.resources.deployment-script.yml | 1 + .github/workflows/avm.res.resources.resource-group.yml | 1 + .github/workflows/avm.res.search.search-service.yml | 1 + .github/workflows/avm.res.service-bus.namespace.yml | 1 + .github/workflows/avm.res.signal-r-service.signal-r.yml | 1 + .github/workflows/avm.res.signal-r-service.web-pub-sub.yml | 1 + .github/workflows/avm.res.sql.server.yml | 1 + .github/workflows/avm.res.storage.storage-account.yml | 1 + .github/workflows/avm.res.synapse.private-link-hub.yml | 1 + .github/workflows/avm.res.synapse.workspace.yml | 1 + .../workflows/avm.res.virtual-machine-images.image-template.yml | 1 + .github/workflows/avm.res.web.serverfarm.yml | 1 + .github/workflows/avm.res.web.site.yml | 1 + .github/workflows/avm.res.web.static-site.yml | 1 + 111 files changed, 111 insertions(+) diff --git a/.github/workflows/avm.res.analysis-services.server.yml b/.github/workflows/avm.res.analysis-services.server.yml index d4fb75c88c..f0423cebc1 100644 --- a/.github/workflows/avm.res.analysis-services.server.yml +++ b/.github/workflows/avm.res.analysis-services.server.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.analysis-services.server.yml" - "avm/res/analysis-services/server/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.api-management.service.yml b/.github/workflows/avm.res.api-management.service.yml index e076b66d14..e50143e5eb 100644 --- a/.github/workflows/avm.res.api-management.service.yml +++ b/.github/workflows/avm.res.api-management.service.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.api-management.service.yml" - "avm/res/api-management/service/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.app-configuration.configuration-store.yml b/.github/workflows/avm.res.app-configuration.configuration-store.yml index a503146787..64007151e5 100644 --- a/.github/workflows/avm.res.app-configuration.configuration-store.yml +++ b/.github/workflows/avm.res.app-configuration.configuration-store.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.app-configuration.configuration-store.yml" - "avm/res/app-configuration/configuration-store/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.app.container-app.yml b/.github/workflows/avm.res.app.container-app.yml index ebe9a53b02..eda9086f29 100644 --- a/.github/workflows/avm.res.app.container-app.yml +++ b/.github/workflows/avm.res.app.container-app.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.app.container-app.yml" - "avm/res/app/container-app/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.app.managed-environment.yml b/.github/workflows/avm.res.app.managed-environment.yml index 1abf7ed421..9870549e1b 100644 --- a/.github/workflows/avm.res.app.managed-environment.yml +++ b/.github/workflows/avm.res.app.managed-environment.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.app.managed-environment.yml" - "avm/res/app/managed-environment/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.automation.automation-account.yml b/.github/workflows/avm.res.automation.automation-account.yml index 4b1c846214..a1d821360d 100644 --- a/.github/workflows/avm.res.automation.automation-account.yml +++ b/.github/workflows/avm.res.automation.automation-account.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.automation.automation-account.yml" - "avm/res/automation/automation-account/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.batch.batch-account.yml b/.github/workflows/avm.res.batch.batch-account.yml index bc2c84337b..9a6a729a15 100644 --- a/.github/workflows/avm.res.batch.batch-account.yml +++ b/.github/workflows/avm.res.batch.batch-account.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.batch.batch-account.yml" - "avm/res/batch/batch-account/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.cache.redis.yml b/.github/workflows/avm.res.cache.redis.yml index 27878ecb1c..ac43a0e789 100644 --- a/.github/workflows/avm.res.cache.redis.yml +++ b/.github/workflows/avm.res.cache.redis.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.cache.redis.yml" - "avm/res/cache/redis/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.cdn.profile.yml b/.github/workflows/avm.res.cdn.profile.yml index 06fecbe878..59cc7b8ee8 100644 --- a/.github/workflows/avm.res.cdn.profile.yml +++ b/.github/workflows/avm.res.cdn.profile.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.cdn.profile.yml" - "avm/res/cdn/profile/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.cognitive-services.account.yml b/.github/workflows/avm.res.cognitive-services.account.yml index 7ce13dc9e0..bf98e748fd 100644 --- a/.github/workflows/avm.res.cognitive-services.account.yml +++ b/.github/workflows/avm.res.cognitive-services.account.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.cognitive-services.account.yml" - "avm/res/cognitive-services/account/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.compute.availability-set.yml b/.github/workflows/avm.res.compute.availability-set.yml index 954ad6d863..9d8262d723 100644 --- a/.github/workflows/avm.res.compute.availability-set.yml +++ b/.github/workflows/avm.res.compute.availability-set.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.compute.availability-set.yml" - "avm/res/compute/availability-set/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.compute.disk-encryption-set.yml b/.github/workflows/avm.res.compute.disk-encryption-set.yml index 6ebcb587cb..d100ca82d4 100644 --- a/.github/workflows/avm.res.compute.disk-encryption-set.yml +++ b/.github/workflows/avm.res.compute.disk-encryption-set.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.compute.disk-encryption-set.yml" - "avm/res/compute/disk-encryption-set/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.compute.disk.yml b/.github/workflows/avm.res.compute.disk.yml index e7ffab5ca5..532b8d3395 100644 --- a/.github/workflows/avm.res.compute.disk.yml +++ b/.github/workflows/avm.res.compute.disk.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.compute.disk.yml" - "avm/res/compute/disk/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.compute.gallery.yml b/.github/workflows/avm.res.compute.gallery.yml index 234cb2df96..ecd2971eac 100644 --- a/.github/workflows/avm.res.compute.gallery.yml +++ b/.github/workflows/avm.res.compute.gallery.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.compute.gallery.yml" - "avm/res/compute/gallery/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.compute.image.yml b/.github/workflows/avm.res.compute.image.yml index cb9f4a0ea8..34d2ddbf84 100644 --- a/.github/workflows/avm.res.compute.image.yml +++ b/.github/workflows/avm.res.compute.image.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.compute.image.yml" - "avm/res/compute/image/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.compute.proximity-placement-group.yml b/.github/workflows/avm.res.compute.proximity-placement-group.yml index d5c7c38252..203bcda2f6 100644 --- a/.github/workflows/avm.res.compute.proximity-placement-group.yml +++ b/.github/workflows/avm.res.compute.proximity-placement-group.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.compute.proximity-placement-group.yml" - "avm/res/compute/proximity-placement-group/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.compute.ssh-public-key.yml b/.github/workflows/avm.res.compute.ssh-public-key.yml index b4a494abaf..f6009ff23f 100644 --- a/.github/workflows/avm.res.compute.ssh-public-key.yml +++ b/.github/workflows/avm.res.compute.ssh-public-key.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.compute.ssh-public-key.yml" - "avm/res/compute/ssh-public-key/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.compute.virtual-machine-scale-set.yml b/.github/workflows/avm.res.compute.virtual-machine-scale-set.yml index 4fde36170e..6684d6ac6f 100644 --- a/.github/workflows/avm.res.compute.virtual-machine-scale-set.yml +++ b/.github/workflows/avm.res.compute.virtual-machine-scale-set.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.compute.virtual-machine-scale-set.yml" - "avm/res/compute/virtual-machine-scale-set/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.compute.virtual-machine.yml b/.github/workflows/avm.res.compute.virtual-machine.yml index 5e831a9034..ea05134a0c 100644 --- a/.github/workflows/avm.res.compute.virtual-machine.yml +++ b/.github/workflows/avm.res.compute.virtual-machine.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.compute.virtual-machine.yml" - "avm/res/compute/virtual-machine/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.consumption.budget.yml b/.github/workflows/avm.res.consumption.budget.yml index f93a5da2d3..90b490e86b 100644 --- a/.github/workflows/avm.res.consumption.budget.yml +++ b/.github/workflows/avm.res.consumption.budget.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.consumption.budget.yml" - "avm/res/consumption/budget/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.container-registry.registry.yml b/.github/workflows/avm.res.container-registry.registry.yml index d7e65d9705..3337589732 100644 --- a/.github/workflows/avm.res.container-registry.registry.yml +++ b/.github/workflows/avm.res.container-registry.registry.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.container-registry.registry.yml" - "avm/res/container-registry/registry/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.container-service.managed-cluster.yml b/.github/workflows/avm.res.container-service.managed-cluster.yml index d2ab01232f..09fe56615a 100644 --- a/.github/workflows/avm.res.container-service.managed-cluster.yml +++ b/.github/workflows/avm.res.container-service.managed-cluster.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.container-service.managed-cluster.yml" - "avm/res/container-service/managed-cluster/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.data-factory.factory.yml b/.github/workflows/avm.res.data-factory.factory.yml index ce1f6e6402..85f84e0b07 100644 --- a/.github/workflows/avm.res.data-factory.factory.yml +++ b/.github/workflows/avm.res.data-factory.factory.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.data-factory.factory.yml" - "avm/res/data-factory/factory/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.data-protection.backup-vault.yml b/.github/workflows/avm.res.data-protection.backup-vault.yml index 4f43ab3885..a7bb6a820b 100644 --- a/.github/workflows/avm.res.data-protection.backup-vault.yml +++ b/.github/workflows/avm.res.data-protection.backup-vault.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.data-protection.backup-vault.yml" - "avm/res/data-protection/backup-vault/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.databricks.access-connector.yml b/.github/workflows/avm.res.databricks.access-connector.yml index 5b672a4384..148b0f3b47 100644 --- a/.github/workflows/avm.res.databricks.access-connector.yml +++ b/.github/workflows/avm.res.databricks.access-connector.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.databricks.access-connector.yml" - "avm/res/databricks/access-connector/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.databricks.workspace.yml b/.github/workflows/avm.res.databricks.workspace.yml index e9a182ba0f..c77a174cc5 100644 --- a/.github/workflows/avm.res.databricks.workspace.yml +++ b/.github/workflows/avm.res.databricks.workspace.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.databricks.workspace.yml" - "avm/res/databricks/workspace/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.db-for-my-sql.flexible-server.yml b/.github/workflows/avm.res.db-for-my-sql.flexible-server.yml index 67f321a9de..e3db3a2282 100644 --- a/.github/workflows/avm.res.db-for-my-sql.flexible-server.yml +++ b/.github/workflows/avm.res.db-for-my-sql.flexible-server.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.db-for-my-sql.flexible-server.yml" - "avm/res/db-for-my-sql/flexible-server/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.db-for-postgre-sql.flexible-server.yml b/.github/workflows/avm.res.db-for-postgre-sql.flexible-server.yml index 95e584231b..1f1cc20472 100644 --- a/.github/workflows/avm.res.db-for-postgre-sql.flexible-server.yml +++ b/.github/workflows/avm.res.db-for-postgre-sql.flexible-server.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.db-for-postgre-sql.flexible-server.yml" - "avm/res/db-for-postgre-sql/flexible-server/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.desktop-virtualization.application-group.yml b/.github/workflows/avm.res.desktop-virtualization.application-group.yml index f3392cacf2..cfaf4c73d1 100644 --- a/.github/workflows/avm.res.desktop-virtualization.application-group.yml +++ b/.github/workflows/avm.res.desktop-virtualization.application-group.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.desktop-virtualization.application-group.yml" - "avm/res/desktop-virtualization/application-group/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.desktop-virtualization.host-pool.yml b/.github/workflows/avm.res.desktop-virtualization.host-pool.yml index 77450dc9d6..acd977b9fc 100644 --- a/.github/workflows/avm.res.desktop-virtualization.host-pool.yml +++ b/.github/workflows/avm.res.desktop-virtualization.host-pool.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.desktop-virtualization.host-pool.yml" - "avm/res/desktop-virtualization/host-pool/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.desktop-virtualization.scaling-plan.yml b/.github/workflows/avm.res.desktop-virtualization.scaling-plan.yml index de7552a17a..354e66c840 100644 --- a/.github/workflows/avm.res.desktop-virtualization.scaling-plan.yml +++ b/.github/workflows/avm.res.desktop-virtualization.scaling-plan.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.desktop-virtualization.scaling-plan.yml" - "avm/res/desktop-virtualization/scaling-plan/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.desktop-virtualization.workspace.yml b/.github/workflows/avm.res.desktop-virtualization.workspace.yml index 01eee9836a..a975191730 100644 --- a/.github/workflows/avm.res.desktop-virtualization.workspace.yml +++ b/.github/workflows/avm.res.desktop-virtualization.workspace.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.desktop-virtualization.workspace.yml" - "avm/res/desktop-virtualization/workspace/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.dev-test-lab.lab.yml b/.github/workflows/avm.res.dev-test-lab.lab.yml index b4deffc2c0..f21b83d851 100644 --- a/.github/workflows/avm.res.dev-test-lab.lab.yml +++ b/.github/workflows/avm.res.dev-test-lab.lab.yml @@ -30,6 +30,7 @@ on: - ".github/workflows/avm.res.dev-test-lab.lab.yml" - "avm/res/dev-test-lab/lab/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.document-db.database-account.yml b/.github/workflows/avm.res.document-db.database-account.yml index 9ddf9963a7..0256cf706b 100644 --- a/.github/workflows/avm.res.document-db.database-account.yml +++ b/.github/workflows/avm.res.document-db.database-account.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.document-db.database-account.yml" - "avm/res/document-db/database-account/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.event-grid.domain.yml b/.github/workflows/avm.res.event-grid.domain.yml index 805d86382a..9381b46be3 100644 --- a/.github/workflows/avm.res.event-grid.domain.yml +++ b/.github/workflows/avm.res.event-grid.domain.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.event-grid.domain.yml" - "avm/res/event-grid/domain/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.event-grid.namespace.yml b/.github/workflows/avm.res.event-grid.namespace.yml index 59046c0cc4..918be160e4 100644 --- a/.github/workflows/avm.res.event-grid.namespace.yml +++ b/.github/workflows/avm.res.event-grid.namespace.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.event-grid.namespace.yml" - "avm/res/event-grid/namespace/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.event-grid.system-topic.yml b/.github/workflows/avm.res.event-grid.system-topic.yml index 4098fe7bb3..91a39b0702 100644 --- a/.github/workflows/avm.res.event-grid.system-topic.yml +++ b/.github/workflows/avm.res.event-grid.system-topic.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.event-grid.system-topic.yml" - "avm/res/event-grid/system-topic/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.event-grid.topic.yml b/.github/workflows/avm.res.event-grid.topic.yml index 4a698ff8d4..c18831793c 100644 --- a/.github/workflows/avm.res.event-grid.topic.yml +++ b/.github/workflows/avm.res.event-grid.topic.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.event-grid.topic.yml" - "avm/res/event-grid/topic/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.event-hub.namespace.yml b/.github/workflows/avm.res.event-hub.namespace.yml index fd751cc11d..fdb60c6967 100644 --- a/.github/workflows/avm.res.event-hub.namespace.yml +++ b/.github/workflows/avm.res.event-hub.namespace.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.event-hub.namespace.yml" - "avm/res/event-hub/namespace/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.health-bot.health-bot.yml b/.github/workflows/avm.res.health-bot.health-bot.yml index fbe7dd559c..2816874657 100644 --- a/.github/workflows/avm.res.health-bot.health-bot.yml +++ b/.github/workflows/avm.res.health-bot.health-bot.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.health-bot.health-bot.yml" - "avm/res/health-bot/health-bot/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.insights.action-group.yml b/.github/workflows/avm.res.insights.action-group.yml index de5630285f..e1ab58c33d 100644 --- a/.github/workflows/avm.res.insights.action-group.yml +++ b/.github/workflows/avm.res.insights.action-group.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.insights.action-group.yml" - "avm/res/insights/action-group/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.insights.activity-log-alert.yml b/.github/workflows/avm.res.insights.activity-log-alert.yml index dc088352d5..56909df497 100644 --- a/.github/workflows/avm.res.insights.activity-log-alert.yml +++ b/.github/workflows/avm.res.insights.activity-log-alert.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.insights.activity-log-alert.yml" - "avm/res/insights/activity-log-alert/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.insights.component.yml b/.github/workflows/avm.res.insights.component.yml index 877f4d4440..9a050de1b3 100644 --- a/.github/workflows/avm.res.insights.component.yml +++ b/.github/workflows/avm.res.insights.component.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.insights.component.yml" - "avm/res/insights/component/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.insights.data-collection-endpoint.yml b/.github/workflows/avm.res.insights.data-collection-endpoint.yml index 11af5da538..4378fd0524 100644 --- a/.github/workflows/avm.res.insights.data-collection-endpoint.yml +++ b/.github/workflows/avm.res.insights.data-collection-endpoint.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.insights.data-collection-endpoint.yml" - "avm/res/insights/data-collection-endpoint/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.insights.data-collection-rule.yml b/.github/workflows/avm.res.insights.data-collection-rule.yml index 4e1a5ba34f..38f40faa0f 100644 --- a/.github/workflows/avm.res.insights.data-collection-rule.yml +++ b/.github/workflows/avm.res.insights.data-collection-rule.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.insights.data-collection-rule.yml" - "avm/res/insights/data-collection-rule/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.insights.diagnostic-setting.yml b/.github/workflows/avm.res.insights.diagnostic-setting.yml index 04a17f3706..795331cb39 100644 --- a/.github/workflows/avm.res.insights.diagnostic-setting.yml +++ b/.github/workflows/avm.res.insights.diagnostic-setting.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.insights.diagnostic-setting.yml" - "avm/res/insights/diagnostic-setting/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.insights.metric-alert.yml b/.github/workflows/avm.res.insights.metric-alert.yml index 7b45d7709c..9257fd9da0 100644 --- a/.github/workflows/avm.res.insights.metric-alert.yml +++ b/.github/workflows/avm.res.insights.metric-alert.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.insights.metric-alert.yml" - "avm/res/insights/metric-alert/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.insights.private-link-scope.yml b/.github/workflows/avm.res.insights.private-link-scope.yml index 7c353ac15c..cef950e2d1 100644 --- a/.github/workflows/avm.res.insights.private-link-scope.yml +++ b/.github/workflows/avm.res.insights.private-link-scope.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.insights.private-link-scope.yml" - "avm/res/insights/private-link-scope/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.insights.scheduled-query-rule.yml b/.github/workflows/avm.res.insights.scheduled-query-rule.yml index 95f4e28d9f..cc8498a9e2 100644 --- a/.github/workflows/avm.res.insights.scheduled-query-rule.yml +++ b/.github/workflows/avm.res.insights.scheduled-query-rule.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.insights.scheduled-query-rule.yml" - "avm/res/insights/scheduled-query-rule/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.insights.webtest.yml b/.github/workflows/avm.res.insights.webtest.yml index 169f66747e..56170b2b41 100644 --- a/.github/workflows/avm.res.insights.webtest.yml +++ b/.github/workflows/avm.res.insights.webtest.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.insights.webtest.yml" - "avm/res/insights/webtest/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.key-vault.vault.yml b/.github/workflows/avm.res.key-vault.vault.yml index 35c2a196ca..5968981b0a 100644 --- a/.github/workflows/avm.res.key-vault.vault.yml +++ b/.github/workflows/avm.res.key-vault.vault.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.key-vault.vault.yml" - "avm/res/key-vault/vault/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.kubernetes-configuration.extension.yml b/.github/workflows/avm.res.kubernetes-configuration.extension.yml index 255370b8c4..a64e3ec6ae 100644 --- a/.github/workflows/avm.res.kubernetes-configuration.extension.yml +++ b/.github/workflows/avm.res.kubernetes-configuration.extension.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.kubernetes-configuration.extension.yml" - "avm/res/kubernetes-configuration/extension/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.kubernetes-configuration.flux-configuration.yml b/.github/workflows/avm.res.kubernetes-configuration.flux-configuration.yml index e00e543251..c2b6639e50 100644 --- a/.github/workflows/avm.res.kubernetes-configuration.flux-configuration.yml +++ b/.github/workflows/avm.res.kubernetes-configuration.flux-configuration.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.kubernetes-configuration.flux-configuration.yml" - "avm/res/kubernetes-configuration/flux-configuration/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.logic.workflow.yml b/.github/workflows/avm.res.logic.workflow.yml index c5c823eb5e..4e26779ac4 100644 --- a/.github/workflows/avm.res.logic.workflow.yml +++ b/.github/workflows/avm.res.logic.workflow.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.logic.workflow" - "avm/res/logic/workflow/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.machine-learning-services.workspace.yml b/.github/workflows/avm.res.machine-learning-services.workspace.yml index 607a52f651..0870695a7b 100644 --- a/.github/workflows/avm.res.machine-learning-services.workspace.yml +++ b/.github/workflows/avm.res.machine-learning-services.workspace.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.machine-learning-services.workspace.yml" - "avm/res/machine-learning-services/workspace/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.maintenance.maintenance-configuration.yml b/.github/workflows/avm.res.maintenance.maintenance-configuration.yml index 9ba597eb51..557b54b823 100644 --- a/.github/workflows/avm.res.maintenance.maintenance-configuration.yml +++ b/.github/workflows/avm.res.maintenance.maintenance-configuration.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.maintenance.maintenance-configuration.yml" - "avm/res/maintenance/maintenance-configuration/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.managed-identity.user-assigned-identity.yml b/.github/workflows/avm.res.managed-identity.user-assigned-identity.yml index 4c953bb184..091029721e 100644 --- a/.github/workflows/avm.res.managed-identity.user-assigned-identity.yml +++ b/.github/workflows/avm.res.managed-identity.user-assigned-identity.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.managed-identity.user-assigned-identity.yml" - "avm/res/managed-identity/user-assigned-identity/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.management.management-group.yml b/.github/workflows/avm.res.management.management-group.yml index 1e90874a6c..2cba65a51f 100644 --- a/.github/workflows/avm.res.management.management-group.yml +++ b/.github/workflows/avm.res.management.management-group.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.management.management-group.yml" - "avm/res/management/management-group/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.net-app.net-app-account.yml b/.github/workflows/avm.res.net-app.net-app-account.yml index 983aa5bf30..072606e52d 100644 --- a/.github/workflows/avm.res.net-app.net-app-account.yml +++ b/.github/workflows/avm.res.net-app.net-app-account.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.net-app.net-app-account.yml" - "avm/res/net-app/net-app-account/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.application-security-group.yml b/.github/workflows/avm.res.network.application-security-group.yml index c4cad4cf66..dd6a8ea197 100644 --- a/.github/workflows/avm.res.network.application-security-group.yml +++ b/.github/workflows/avm.res.network.application-security-group.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.application-security-group.yml" - "avm/res/network/application-security-group/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.azure-firewall.yml b/.github/workflows/avm.res.network.azure-firewall.yml index 7e6a0195c1..e17568a3aa 100644 --- a/.github/workflows/avm.res.network.azure-firewall.yml +++ b/.github/workflows/avm.res.network.azure-firewall.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.azure-firewall.yml" - "avm/res/network/azure-firewall/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.bastion-host.yml b/.github/workflows/avm.res.network.bastion-host.yml index 6dd2ecf7cf..2200b41740 100644 --- a/.github/workflows/avm.res.network.bastion-host.yml +++ b/.github/workflows/avm.res.network.bastion-host.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.bastion-host.yml" - "avm/res/network/bastion-host/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.connection.yml b/.github/workflows/avm.res.network.connection.yml index 4c7108516f..66808c8311 100644 --- a/.github/workflows/avm.res.network.connection.yml +++ b/.github/workflows/avm.res.network.connection.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.connection.yml" - "avm/res/network/connection/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.ddos-protection-plan.yml b/.github/workflows/avm.res.network.ddos-protection-plan.yml index 6007a83daf..a496035ec7 100644 --- a/.github/workflows/avm.res.network.ddos-protection-plan.yml +++ b/.github/workflows/avm.res.network.ddos-protection-plan.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.ddos-protection-plan.yml" - "avm/res/network/ddos-protection-plan/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.dns-forwarding-ruleset.yml b/.github/workflows/avm.res.network.dns-forwarding-ruleset.yml index 14831d3af5..09fd3b93bb 100644 --- a/.github/workflows/avm.res.network.dns-forwarding-ruleset.yml +++ b/.github/workflows/avm.res.network.dns-forwarding-ruleset.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.dns-forwarding-ruleset.yml" - "avm/res/network/dns-forwarding-ruleset/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.dns-resolver.yml b/.github/workflows/avm.res.network.dns-resolver.yml index 00ade7479a..8ade3fca08 100644 --- a/.github/workflows/avm.res.network.dns-resolver.yml +++ b/.github/workflows/avm.res.network.dns-resolver.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.dns-resolver.yml" - "avm/res/network/dns-resolver/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.dns-zone.yml b/.github/workflows/avm.res.network.dns-zone.yml index 4249d6a6bb..30a7251dd1 100644 --- a/.github/workflows/avm.res.network.dns-zone.yml +++ b/.github/workflows/avm.res.network.dns-zone.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.dns-zone.yml" - "avm/res/network/dns-zone/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.express-route-circuit.yml b/.github/workflows/avm.res.network.express-route-circuit.yml index 05a6f9a77a..c0284316a4 100644 --- a/.github/workflows/avm.res.network.express-route-circuit.yml +++ b/.github/workflows/avm.res.network.express-route-circuit.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.express-route-circuit.yml" - "avm/res/network/express-route-circuit/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.express-route-gateway.yml b/.github/workflows/avm.res.network.express-route-gateway.yml index 32ee0d53fd..cd309a876c 100644 --- a/.github/workflows/avm.res.network.express-route-gateway.yml +++ b/.github/workflows/avm.res.network.express-route-gateway.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.express-route-gateway.yml" - "avm/res/network/express-route-gateway/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.firewall-policy.yml b/.github/workflows/avm.res.network.firewall-policy.yml index 297f00f196..f9afa2c914 100644 --- a/.github/workflows/avm.res.network.firewall-policy.yml +++ b/.github/workflows/avm.res.network.firewall-policy.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.firewall-policy.yml" - "avm/res/network/firewall-policy/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.front-door-web-application-firewall-policy.yml b/.github/workflows/avm.res.network.front-door-web-application-firewall-policy.yml index cce205fd07..b0cf5b7adf 100644 --- a/.github/workflows/avm.res.network.front-door-web-application-firewall-policy.yml +++ b/.github/workflows/avm.res.network.front-door-web-application-firewall-policy.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.front-door-web-application-firewall-policy.yml" - "avm/res/network/front-door-web-application-firewall-policy/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.front-door.yml b/.github/workflows/avm.res.network.front-door.yml index 7e9c2b065c..aeebe4b8e0 100644 --- a/.github/workflows/avm.res.network.front-door.yml +++ b/.github/workflows/avm.res.network.front-door.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.front-door.yml" - "avm/res/network/front-door/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.ip-group.yml b/.github/workflows/avm.res.network.ip-group.yml index 4da94cdffb..beae160b06 100644 --- a/.github/workflows/avm.res.network.ip-group.yml +++ b/.github/workflows/avm.res.network.ip-group.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.ip-group.yml" - "avm/res/network/ip-group/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.load-balancer.yml b/.github/workflows/avm.res.network.load-balancer.yml index b7b9c2c9e7..82d767037a 100644 --- a/.github/workflows/avm.res.network.load-balancer.yml +++ b/.github/workflows/avm.res.network.load-balancer.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.load-balancer.yml" - "avm/res/network/load-balancer/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.local-network-gateway.yml b/.github/workflows/avm.res.network.local-network-gateway.yml index 7a5d795615..4bd6d37c06 100644 --- a/.github/workflows/avm.res.network.local-network-gateway.yml +++ b/.github/workflows/avm.res.network.local-network-gateway.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.local-network-gateway.yml" - "avm/res/network/local-network-gateway/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.nat-gateway.yml b/.github/workflows/avm.res.network.nat-gateway.yml index ae2862141e..9225b5fa7d 100644 --- a/.github/workflows/avm.res.network.nat-gateway.yml +++ b/.github/workflows/avm.res.network.nat-gateway.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.nat-gateway.yml" - "avm/res/network/nat-gateway/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.network-interface.yml b/.github/workflows/avm.res.network.network-interface.yml index 39687b1d28..9e7fd880dd 100644 --- a/.github/workflows/avm.res.network.network-interface.yml +++ b/.github/workflows/avm.res.network.network-interface.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.network-interface.yml" - "avm/res/network/network-interface/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.network-manager.yml b/.github/workflows/avm.res.network.network-manager.yml index a0a003312a..de51d0761f 100644 --- a/.github/workflows/avm.res.network.network-manager.yml +++ b/.github/workflows/avm.res.network.network-manager.yml @@ -30,6 +30,7 @@ on: - ".github/workflows/avm.res.network.network-manager.yml" - "avm/res/network/network-manager/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.network-security-group.yml b/.github/workflows/avm.res.network.network-security-group.yml index bb8af63b9b..daa4e72f0e 100644 --- a/.github/workflows/avm.res.network.network-security-group.yml +++ b/.github/workflows/avm.res.network.network-security-group.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.network-security-group.yml" - "avm/res/network/network-security-group/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.private-dns-zone.yml b/.github/workflows/avm.res.network.private-dns-zone.yml index 767024712f..5a4e8317d9 100644 --- a/.github/workflows/avm.res.network.private-dns-zone.yml +++ b/.github/workflows/avm.res.network.private-dns-zone.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.private-dns-zone.yml" - "avm/res/network/private-dns-zone/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.private-endpoint.yml b/.github/workflows/avm.res.network.private-endpoint.yml index e833da872f..5d23ab8081 100644 --- a/.github/workflows/avm.res.network.private-endpoint.yml +++ b/.github/workflows/avm.res.network.private-endpoint.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.private-endpoint.yml" - "avm/res/network/private-endpoint/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.private-link-service.yml b/.github/workflows/avm.res.network.private-link-service.yml index 19784ca217..c07fda9761 100644 --- a/.github/workflows/avm.res.network.private-link-service.yml +++ b/.github/workflows/avm.res.network.private-link-service.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.private-link-service.yml" - "avm/res/network/private-link-service/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.public-ip-address.yml b/.github/workflows/avm.res.network.public-ip-address.yml index 2bdc24293d..db38984755 100644 --- a/.github/workflows/avm.res.network.public-ip-address.yml +++ b/.github/workflows/avm.res.network.public-ip-address.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.public-ip-address.yml" - "avm/res/network/public-ip-address/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.public-ip-prefix.yml b/.github/workflows/avm.res.network.public-ip-prefix.yml index 862a95a251..efe48d6ba0 100644 --- a/.github/workflows/avm.res.network.public-ip-prefix.yml +++ b/.github/workflows/avm.res.network.public-ip-prefix.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.public-ip-prefix.yml" - "avm/res/network/public-ip-prefix/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.route-table.yml b/.github/workflows/avm.res.network.route-table.yml index d287d86799..8dd1c6e2dd 100644 --- a/.github/workflows/avm.res.network.route-table.yml +++ b/.github/workflows/avm.res.network.route-table.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.route-table.yml" - "avm/res/network/route-table/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.trafficmanagerprofile.yml b/.github/workflows/avm.res.network.trafficmanagerprofile.yml index 9cdaa3afdd..fe5f3c4216 100644 --- a/.github/workflows/avm.res.network.trafficmanagerprofile.yml +++ b/.github/workflows/avm.res.network.trafficmanagerprofile.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.trafficmanagerprofile" - "avm/res/network/trafficmanagerprofile/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.virtual-hub.yml b/.github/workflows/avm.res.network.virtual-hub.yml index 2cb6561fbe..07eb5900cc 100644 --- a/.github/workflows/avm.res.network.virtual-hub.yml +++ b/.github/workflows/avm.res.network.virtual-hub.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.virtual-hub.yml" - "avm/res/network/virtual-hub/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.virtual-network-gateway.yml b/.github/workflows/avm.res.network.virtual-network-gateway.yml index f72cd8ec3b..f3603f6a93 100644 --- a/.github/workflows/avm.res.network.virtual-network-gateway.yml +++ b/.github/workflows/avm.res.network.virtual-network-gateway.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.virtual-network-gateway.yml" - "avm/res/network/virtual-network-gateway/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.virtual-network.yml b/.github/workflows/avm.res.network.virtual-network.yml index 5162d2e3dd..19dcc10683 100644 --- a/.github/workflows/avm.res.network.virtual-network.yml +++ b/.github/workflows/avm.res.network.virtual-network.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.virtual-network.yml" - "avm/res/network/virtual-network/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.virtual-wan.yml b/.github/workflows/avm.res.network.virtual-wan.yml index a0a1c6f5ce..2e0cb52e58 100644 --- a/.github/workflows/avm.res.network.virtual-wan.yml +++ b/.github/workflows/avm.res.network.virtual-wan.yml @@ -30,6 +30,7 @@ on: - ".github/workflows/avm.res.network.virtual-wan.yml" - "avm/res/network/virtual-wan/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.vpn-gateway.yml b/.github/workflows/avm.res.network.vpn-gateway.yml index 7d38ba8802..cad31de2f0 100644 --- a/.github/workflows/avm.res.network.vpn-gateway.yml +++ b/.github/workflows/avm.res.network.vpn-gateway.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.vpn-gateway.yml" - "avm/res/network/vpn-gateway/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.network.vpn-site.yml b/.github/workflows/avm.res.network.vpn-site.yml index b80c8d13f8..9bd6329f4b 100644 --- a/.github/workflows/avm.res.network.vpn-site.yml +++ b/.github/workflows/avm.res.network.vpn-site.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.network.vpn-site.yml" - "avm/res/network/vpn-site/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.operational-insights.workspace.yml b/.github/workflows/avm.res.operational-insights.workspace.yml index 3eff0bc498..58e95538ae 100644 --- a/.github/workflows/avm.res.operational-insights.workspace.yml +++ b/.github/workflows/avm.res.operational-insights.workspace.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.operational-insights.workspace.yml" - "avm/res/operational-insights/workspace/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.operations-management.solution.yml b/.github/workflows/avm.res.operations-management.solution.yml index 29224ff36f..d91fa4e81d 100644 --- a/.github/workflows/avm.res.operations-management.solution.yml +++ b/.github/workflows/avm.res.operations-management.solution.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.operations-management.solution.yml" - "avm/res/operations-management/solution/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.power-bi-dedicated.capacity.yml b/.github/workflows/avm.res.power-bi-dedicated.capacity.yml index 23fcce45cc..318a6ac32e 100644 --- a/.github/workflows/avm.res.power-bi-dedicated.capacity.yml +++ b/.github/workflows/avm.res.power-bi-dedicated.capacity.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.power-bi-dedicated.capacity.yml" - "avm/res/power-bi-dedicated/capacity/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.purview.account.yml b/.github/workflows/avm.res.purview.account.yml index 66ad311df5..a32032f4cc 100644 --- a/.github/workflows/avm.res.purview.account.yml +++ b/.github/workflows/avm.res.purview.account.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.purview.account.yml" - "avm/res/purview/account/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.resource-graph.query.yml b/.github/workflows/avm.res.resource-graph.query.yml index 9d3d3135bf..cf6dbea554 100644 --- a/.github/workflows/avm.res.resource-graph.query.yml +++ b/.github/workflows/avm.res.resource-graph.query.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.resource-graph.query.yml" - "avm/res/resource-graph/query/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.resources.deployment-script.yml b/.github/workflows/avm.res.resources.deployment-script.yml index 1169625faa..83fe844bf5 100644 --- a/.github/workflows/avm.res.resources.deployment-script.yml +++ b/.github/workflows/avm.res.resources.deployment-script.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.resources.deployment-script" - "avm/res/resources/deployment-script/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.resources.resource-group.yml b/.github/workflows/avm.res.resources.resource-group.yml index aeededb915..1029a71532 100644 --- a/.github/workflows/avm.res.resources.resource-group.yml +++ b/.github/workflows/avm.res.resources.resource-group.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.resources.resource-group.yml" - "avm/res/resources/resource-group/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.search.search-service.yml b/.github/workflows/avm.res.search.search-service.yml index 6b6139d7ee..bc1cee5a31 100644 --- a/.github/workflows/avm.res.search.search-service.yml +++ b/.github/workflows/avm.res.search.search-service.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.search.search-service.yml" - "avm/res/search/search-service/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.service-bus.namespace.yml b/.github/workflows/avm.res.service-bus.namespace.yml index 3fb712c511..cc9f1d73e6 100644 --- a/.github/workflows/avm.res.service-bus.namespace.yml +++ b/.github/workflows/avm.res.service-bus.namespace.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.service-bus.namespace.yml" - "avm/res/service-bus/namespace/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.signal-r-service.signal-r.yml b/.github/workflows/avm.res.signal-r-service.signal-r.yml index d638069e67..4583283181 100644 --- a/.github/workflows/avm.res.signal-r-service.signal-r.yml +++ b/.github/workflows/avm.res.signal-r-service.signal-r.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.signal-r-service.signal-r.yml" - "avm/res/signal-r-service/signal-r/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.signal-r-service.web-pub-sub.yml b/.github/workflows/avm.res.signal-r-service.web-pub-sub.yml index b029617de5..63bfe1a0ae 100644 --- a/.github/workflows/avm.res.signal-r-service.web-pub-sub.yml +++ b/.github/workflows/avm.res.signal-r-service.web-pub-sub.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.signal-r-service.web-pub-sub.yml" - "avm/res/signal-r-service/web-pub-sub/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.sql.server.yml b/.github/workflows/avm.res.sql.server.yml index af8118e4a7..318c70f382 100644 --- a/.github/workflows/avm.res.sql.server.yml +++ b/.github/workflows/avm.res.sql.server.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.sql.server.yml" - "avm/res/sql/server/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.storage.storage-account.yml b/.github/workflows/avm.res.storage.storage-account.yml index 3b39de874a..5463a26207 100644 --- a/.github/workflows/avm.res.storage.storage-account.yml +++ b/.github/workflows/avm.res.storage.storage-account.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.storage.storage-account.yml" - "avm/res/storage/storage-account/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.synapse.private-link-hub.yml b/.github/workflows/avm.res.synapse.private-link-hub.yml index 61536513c7..78d7f36082 100644 --- a/.github/workflows/avm.res.synapse.private-link-hub.yml +++ b/.github/workflows/avm.res.synapse.private-link-hub.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.synapse.private-link-hub.yml" - "avm/res/synapse/private-link-hub/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.synapse.workspace.yml b/.github/workflows/avm.res.synapse.workspace.yml index d44cd5ad6e..37dd6ce412 100644 --- a/.github/workflows/avm.res.synapse.workspace.yml +++ b/.github/workflows/avm.res.synapse.workspace.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.synapse.workspace.yml" - "avm/res/synapse/workspace/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.virtual-machine-images.image-template.yml b/.github/workflows/avm.res.virtual-machine-images.image-template.yml index ad5e833d1e..649b950f18 100644 --- a/.github/workflows/avm.res.virtual-machine-images.image-template.yml +++ b/.github/workflows/avm.res.virtual-machine-images.image-template.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.virtual-machine-images.image-template.yml" - "avm/res/virtual-machine-images/image-template/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.web.serverfarm.yml b/.github/workflows/avm.res.web.serverfarm.yml index 18071040a0..49e6a91d0e 100644 --- a/.github/workflows/avm.res.web.serverfarm.yml +++ b/.github/workflows/avm.res.web.serverfarm.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.web.serverfarm.yml" - "avm/res/web/serverfarm/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.web.site.yml b/.github/workflows/avm.res.web.site.yml index 05714787a4..b0742ae772 100644 --- a/.github/workflows/avm.res.web.site.yml +++ b/.github/workflows/avm.res.web.site.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.web.site.yml" - "avm/res/web/site/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: diff --git a/.github/workflows/avm.res.web.static-site.yml b/.github/workflows/avm.res.web.static-site.yml index 5423969e4b..111370620f 100644 --- a/.github/workflows/avm.res.web.static-site.yml +++ b/.github/workflows/avm.res.web.static-site.yml @@ -29,6 +29,7 @@ on: - ".github/workflows/avm.res.web.static-site.yml" - "avm/res/web/static-site/**" - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: From 98038bb43c7dc38d1f759477fb81e962ca2ec305 Mon Sep 17 00:00:00 2001 From: Alexander Sehr Date: Tue, 19 Mar 2024 23:56:40 +0100 Subject: [PATCH 41/73] feat: Update PE implementation in alignment to latest schema (5) (#1092) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description Follow up to #1070 - Applied latest PE schema accross all modules - Ensured that all modules deploy at least 2 PEs to wnsure there is no concurrency issue - Removed several dedicated `private-endpoint` tests cases if already implemented in max ## Pipeline Reference | Pipeline | | - | [![avm.res.databricks.workspace](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.databricks.workspace.yml/badge.svg?branch=feat%2Fpe-adjustments-962-946-1042_5&event=workflow_dispatch)](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.databricks.workspace.yml) [![avm.res.synapse.workspace](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.synapse.workspace.yml/badge.svg?branch=feat%2Fpe-adjustments-962-946-1042_5&event=workflow_dispatch)](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.synapse.workspace.yml) ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [x] Azure Verified Module updates: - [x] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [x] Update to documentation --------- Co-authored-by: Sebastian Gräf Co-authored-by: Kris Baranek Co-authored-by: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> --- avm/res/databricks/workspace/README.md | 52 +++++++--- avm/res/databricks/workspace/main.bicep | 41 +++++--- avm/res/databricks/workspace/main.json | 64 +++++++------ .../tests/e2e/max/dependencies.bicep | 29 ++++-- .../workspace/tests/e2e/max/main.test.bicep | 10 +- .../tests/e2e/waf-aligned/dependencies.bicep | 8 +- .../tests/e2e/waf-aligned/main.test.bicep | 1 + avm/res/databricks/workspace/version.json | 4 +- avm/res/synapse/workspace/README.md | 96 ++++++++++++++++--- avm/res/synapse/workspace/main.bicep | 45 ++++++--- avm/res/synapse/workspace/main.json | 83 ++++++++-------- .../tests/e2e/defaults/main.test.bicep | 3 + .../tests/e2e/encrwsai/main.test.bicep | 4 +- .../tests/e2e/encrwuai/main.test.bicep | 3 + .../tests/e2e/managedvnet/main.test.bicep | 4 +- .../tests/e2e/max/dependencies.bicep | 24 ++++- .../workspace/tests/e2e/max/main.test.bicep | 37 ++++++- .../tests/e2e/waf-aligned/main.test.bicep | 4 + avm/res/synapse/workspace/version.json | 2 +- 19 files changed, 364 insertions(+), 150 deletions(-) diff --git a/avm/res/databricks/workspace/README.md b/avm/res/databricks/workspace/README.md index 1afe94cb26..b82707c649 100644 --- a/avm/res/databricks/workspace/README.md +++ b/avm/res/databricks/workspace/README.md @@ -145,12 +145,20 @@ module workspace 'br/public:avm/res/databricks/workspace:' = { privateDnsZoneResourceIds: [ '' ] + service: 'databricks_ui_api' subnetResourceId: '' tags: { Environment: 'Non-Prod' Role: 'DeploymentValidation' } } + { + privateDnsZoneResourceIds: [ + '' + ] + service: 'browser_authentication' + subnetResourceId: '' + } ] publicIpName: 'nat-gw-public-ip' publicNetworkAccess: 'Disabled' @@ -280,11 +288,19 @@ module workspace 'br/public:avm/res/databricks/workspace:' = { "privateDnsZoneResourceIds": [ "" ], + "service": "databricks_ui_api", "subnetResourceId": "", "tags": { "Environment": "Non-Prod", "Role": "DeploymentValidation" } + }, + { + "privateDnsZoneResourceIds": [ + "" + ], + "service": "browser_authentication", + "subnetResourceId": "" } ] }, @@ -407,6 +423,7 @@ module workspace 'br/public:avm/res/databricks/workspace:' = { privateDnsZoneResourceIds: [ '' ] + service: 'databricks_ui_api' subnetResourceId: '' tags: { Environment: 'Non-Prod' @@ -525,6 +542,7 @@ module workspace 'br/public:avm/res/databricks/workspace:' = { "privateDnsZoneResourceIds": [ "" ], + "service": "databricks_ui_api", "subnetResourceId": "", "tags": { "Environment": "Non-Prod", @@ -980,6 +998,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". | | [`subnetResourceId`](#parameter-privateendpointssubnetresourceid) | string | Resource ID of the subnet where the endpoint needs to be created. | **Optional parameters** @@ -991,16 +1010,23 @@ Configuration details for private endpoints. For security reasons, it is recomme | [`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. | +| [`isManualConnection`](#parameter-privateendpointsismanualconnection) | bool | If Manual Private Link Connection is required. | | [`location`](#parameter-privateendpointslocation) | string | The location to deploy the private endpoint to. | | [`lock`](#parameter-privateendpointslock) | object | Specify the type of lock. | -| [`manualPrivateLinkServiceConnections`](#parameter-privateendpointsmanualprivatelinkserviceconnections) | array | Manual PrivateLink Service Connections. | +| [`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. | | [`roleAssignments`](#parameter-privateendpointsroleassignments) | array | Array of role assignments to create. | -| [`service`](#parameter-privateendpointsservice) | string | The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". | | [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/resource groups in this deployment. | +### Parameter: `privateEndpoints.service` + +The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file". + +- Required: Yes +- Type: string + ### Parameter: `privateEndpoints.subnetResourceId` Resource ID of the subnet where the endpoint needs to be created. @@ -1114,6 +1140,13 @@ A private IP address obtained from the private endpoint's subnet. - Required: Yes - Type: string +### Parameter: `privateEndpoints.isManualConnection` + +If Manual Private Link Connection is required. + +- Required: No +- Type: bool + ### Parameter: `privateEndpoints.location` The location to deploy the private endpoint to. @@ -1157,12 +1190,12 @@ Specify the name of lock. - Required: No - Type: string -### Parameter: `privateEndpoints.manualPrivateLinkServiceConnections` +### Parameter: `privateEndpoints.manualConnectionRequestMessage` -Manual PrivateLink Service Connections. +A message passed to the owner of the remote resource with the manual connection request. - Required: No -- Type: array +- Type: string ### Parameter: `privateEndpoints.name` @@ -1274,13 +1307,6 @@ The principal type of the assigned principal ID. ] ``` -### Parameter: `privateEndpoints.service` - -The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". - -- Required: No -- Type: string - ### Parameter: `privateEndpoints.tags` Tags to be applied on all resources/resource groups in this deployment. @@ -1491,7 +1517,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.3.3` | Remote reference | +| `br/public:avm/res/network/private-endpoint:0.4.0` | Remote reference | ## Notes diff --git a/avm/res/databricks/workspace/main.bicep b/avm/res/databricks/workspace/main.bicep index 5a9190ab0f..dd88cb1e7c 100644 --- a/avm/res/databricks/workspace/main.bicep +++ b/avm/res/databricks/workspace/main.bicep @@ -287,21 +287,34 @@ resource workspace_roleAssignments 'Microsoft.Authorization/roleAssignments@2022 scope: workspace }] -module workspace_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.3.3' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { +@batchSize(1) +module workspace_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { name: '${uniqueString(deployment().name, location)}-Databricks-PrivateEndpoint-${index}' params: { - privateLinkServiceConnections: [ + name: privateEndpoint.?name ?? 'pep-${last(split(workspace.id, '/'))}-${privateEndpoint.service}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ { - name: name + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(workspace.id, '/'))}-${privateEndpoint.service}-${index}' properties: { privateLinkServiceId: workspace.id groupIds: [ - privateEndpoint.?service ?? 'databricks_ui_api' + privateEndpoint.service ] } } - ] - name: privateEndpoint.?name ?? 'pep-${last(split(workspace.id, '/'))}-${privateEndpoint.?service ?? 'databricks_ui_api'}-${index}' + ] : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(workspace.id, '/'))}-${privateEndpoint.service}-${index}' + properties: { + privateLinkServiceId: workspace.id + groupIds: [ + privateEndpoint.service + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } + ] : null subnetResourceId: privateEndpoint.subnetResourceId enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location @@ -310,7 +323,6 @@ module workspace_privateEndpoints 'br/public:avm/res/network/private-endpoint:0. privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds roleAssignments: privateEndpoint.?roleAssignments tags: privateEndpoint.?tags ?? tags - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections customDnsConfigs: privateEndpoint.?customDnsConfigs ipConfigurations: privateEndpoint.?ipConfigurations applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds @@ -361,15 +373,14 @@ type lockType = { }? 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 service (sub-) type to deploy the private endpoint for. For example "vault" or "blob".') - service: 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 @@ -380,6 +391,13 @@ type privateEndpointType = { @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.') @@ -422,9 +440,6 @@ type privateEndpointType = { @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') tags: object? - @description('Optional. Manual PrivateLink Service Connections.') - manualPrivateLinkServiceConnections: array? - @description('Optional. Enable/Disable usage telemetry for module.') enableTelemetry: bool? }[]? diff --git a/avm/res/databricks/workspace/main.json b/avm/res/databricks/workspace/main.json index 03e8fa6cbb..7e7925b110 100644 --- a/avm/res/databricks/workspace/main.json +++ b/avm/res/databricks/workspace/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "7710672223855991692" + "version": "0.26.54.24096", + "templateHash": "8925128185589273318" }, "name": "Azure Databricks Workspaces", "description": "This module deploys an Azure Databricks Workspace.", @@ -59,9 +59,8 @@ }, "service": { "type": "string", - "nullable": true, "metadata": { - "description": "Optional. The service (sub-) type to deploy the private endpoint for. For example \"vault\" or \"blob\"." + "description": "Required. The subresource to deploy the private endpoint for. For example \"blob\", \"table\", \"queue\" or \"file\"." } }, "subnetResourceId": { @@ -87,6 +86,21 @@ "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": { @@ -195,13 +209,6 @@ "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." } }, - "manualPrivateLinkServiceConnections": { - "type": "array", - "nullable": true, - "metadata": { - "description": "Optional. Manual PrivateLink Service Connections." - } - }, "enableTelemetry": { "type": "bool", "nullable": true, @@ -814,7 +821,9 @@ "workspace_privateEndpoints": { "copy": { "name": "workspace_privateEndpoints", - "count": "[length(coalesce(parameters('privateEndpoints'), createArray()))]" + "count": "[length(coalesce(parameters('privateEndpoints'), createArray()))]", + "mode": "serial", + "batchSize": 1 }, "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -825,22 +834,11 @@ }, "mode": "Incremental", "parameters": { - "privateLinkServiceConnections": { - "value": [ - { - "name": "[parameters('name')]", - "properties": { - "privateLinkServiceId": "[resourceId('Microsoft.Databricks/workspaces', parameters('name'))]", - "groupIds": [ - "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'databricks_ui_api')]" - ] - } - } - ] - }, "name": { - "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.Databricks/workspaces', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'databricks_ui_api'), copyIndex()))]" + "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()], 'manualPrivateLinkServiceConnections'), 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()], 'manualPrivateLinkServiceConnections'), 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]" }, @@ -865,9 +863,6 @@ "tags": { "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" }, - "manualPrivateLinkServiceConnections": { - "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections')]" - }, "customDnsConfigs": { "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customDnsConfigs')]" }, @@ -889,7 +884,7 @@ "_generator": { "name": "bicep", "version": "0.24.24.22086", - "templateHash": "5518855230364102370" + "templateHash": "2592884001616184297" }, "name": "Private Endpoints", "description": "This module deploys a Private Endpoint.", @@ -1254,7 +1249,7 @@ "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.3.3', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.4.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -1471,6 +1466,13 @@ "description": "The location the resource was deployed into." }, "value": "[reference('privateEndpoint', '2023-04-01', 'full').location]" + }, + "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])]" } } } diff --git a/avm/res/databricks/workspace/tests/e2e/max/dependencies.bicep b/avm/res/databricks/workspace/tests/e2e/max/dependencies.bicep index 9a8c73e3f6..b7d9d8756d 100644 --- a/avm/res/databricks/workspace/tests/e2e/max/dependencies.bicep +++ b/avm/res/databricks/workspace/tests/e2e/max/dependencies.bicep @@ -278,15 +278,21 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2022-01-01' = { } subnets: [ { - name: 'defaultSubnet' + name: 'pimarySubnet' properties: { addressPrefix: cidrSubnet(addressPrefix, 20, 0) } } { - name: 'custom-public-subnet' + name: 'secondarySubnet' properties: { addressPrefix: cidrSubnet(addressPrefix, 20, 1) + } + } + { + name: 'publicSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 20, 2) networkSecurityGroup: { id: networkSecurityGroup.id } @@ -301,9 +307,9 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2022-01-01' = { } } { - name: 'custom-private-subnet' + name: 'privateSubnet' properties: { - addressPrefix: cidrSubnet(addressPrefix, 20, 2) + addressPrefix: cidrSubnet(addressPrefix, 20, 3) networkSecurityGroup: { id: networkSecurityGroup.id } @@ -337,14 +343,17 @@ resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { } } -@description('The resource ID of the created Virtual Network Default Subnet.') -output defaultSubnetResourceId string = virtualNetwork.properties.subnets[0].id +@description('The resource ID of the created Virtual Network Primary Subnet.') +output primarySubnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The resource ID of the created Virtual Network Secondary Subnet.') +output secondarySubnetResourceId string = virtualNetwork.properties.subnets[1].id -@description('The name of the created Virtual Network Public Subnet.') -output customPublicSubnetName string = virtualNetwork.properties.subnets[1].name +@description('The name of the 2nd created Virtual Network Public Subnet.') +output customPublicSubnetName string = virtualNetwork.properties.subnets[2].name -@description('The name of the created Virtual Network Private Subnet.') -output customPrivateSubnetName string = virtualNetwork.properties.subnets[2].name +@description('The name of the 3rd created Virtual Network Private Subnet.') +output customPrivateSubnetName string = virtualNetwork.properties.subnets[3].name @description('The resource ID of the created Virtual Network.') output virtualNetworkResourceId string = virtualNetwork.id diff --git a/avm/res/databricks/workspace/tests/e2e/max/main.test.bicep b/avm/res/databricks/workspace/tests/e2e/max/main.test.bicep index d81486d035..3ad243524e 100644 --- a/avm/res/databricks/workspace/tests/e2e/max/main.test.bicep +++ b/avm/res/databricks/workspace/tests/e2e/max/main.test.bicep @@ -151,12 +151,20 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' privateDnsZoneResourceIds: [ nestedDependencies.outputs.privateDNSZoneResourceId ] - subnetResourceId: nestedDependencies.outputs.defaultSubnetResourceId + service: 'databricks_ui_api' + subnetResourceId: nestedDependencies.outputs.primarySubnetResourceId tags: { Environment: 'Non-Prod' Role: 'DeploymentValidation' } } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.secondarySubnetResourceId + service: 'browser_authentication' + } ] managedResourceGroupResourceId: '${subscription().id}/resourceGroups/rg-${resourceGroupName}-managed' requireInfrastructureEncryption: true diff --git a/avm/res/databricks/workspace/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/databricks/workspace/tests/e2e/waf-aligned/dependencies.bicep index 9a8c73e3f6..a09ec9f89e 100644 --- a/avm/res/databricks/workspace/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/databricks/workspace/tests/e2e/waf-aligned/dependencies.bicep @@ -284,7 +284,7 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2022-01-01' = { } } { - name: 'custom-public-subnet' + name: 'publicSubnet' properties: { addressPrefix: cidrSubnet(addressPrefix, 20, 1) networkSecurityGroup: { @@ -301,7 +301,7 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2022-01-01' = { } } { - name: 'custom-private-subnet' + name: 'privateSubnet' properties: { addressPrefix: cidrSubnet(addressPrefix, 20, 2) networkSecurityGroup: { @@ -340,10 +340,10 @@ resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { @description('The resource ID of the created Virtual Network Default Subnet.') output defaultSubnetResourceId string = virtualNetwork.properties.subnets[0].id -@description('The name of the created Virtual Network Public Subnet.') +@description('The name of the 2nd created Virtual Network Public Subnet.') output customPublicSubnetName string = virtualNetwork.properties.subnets[1].name -@description('The name of the created Virtual Network Private Subnet.') +@description('The name of the 3rd created Virtual Network Private Subnet.') output customPrivateSubnetName string = virtualNetwork.properties.subnets[2].name @description('The resource ID of the created Virtual Network.') diff --git a/avm/res/databricks/workspace/tests/e2e/waf-aligned/main.test.bicep b/avm/res/databricks/workspace/tests/e2e/waf-aligned/main.test.bicep index 295696bd5c..c9edeae81c 100644 --- a/avm/res/databricks/workspace/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/databricks/workspace/tests/e2e/waf-aligned/main.test.bicep @@ -134,6 +134,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' privateDnsZoneResourceIds: [ nestedDependencies.outputs.privateDNSZoneResourceId ] + service: 'databricks_ui_api' subnetResourceId: nestedDependencies.outputs.defaultSubnetResourceId tags: { Environment: 'Non-Prod' diff --git a/avm/res/databricks/workspace/version.json b/avm/res/databricks/workspace/version.json index 7fa401bdf7..c177b1bb58 100644 --- a/avm/res/databricks/workspace/version.json +++ b/avm/res/databricks/workspace/version.json @@ -1,7 +1,7 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.1", + "version": "0.3", "pathFilters": [ "./main.json" ] -} +} \ No newline at end of file diff --git a/avm/res/synapse/workspace/README.md b/avm/res/synapse/workspace/README.md index 3c3cea9256..ac0814390f 100644 --- a/avm/res/synapse/workspace/README.md +++ b/avm/res/synapse/workspace/README.md @@ -390,6 +390,37 @@ module workspace 'br/public:avm/res/synapse/workspace:' = { Role: 'DeploymentValidation' } } + { + privateDnsZoneResourceIds: [ + '' + ] + service: 'SQL' + subnetResourceId: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + { + privateDnsZoneResourceIds: [ + '' + ] + service: 'SqlOnDemand' + subnetResourceId: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + { + privateDnsZoneResourceIds: [ + '' + ] + service: 'Dev' + subnetResourceId: '' + } ] roleAssignments: [ { @@ -494,6 +525,37 @@ module workspace 'br/public:avm/res/synapse/workspace:' = { "hidden-title": "This is visible in the resource name", "Role": "DeploymentValidation" } + }, + { + "privateDnsZoneResourceIds": [ + "" + ], + "service": "SQL", + "subnetResourceId": "", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + { + "privateDnsZoneResourceIds": [ + "" + ], + "service": "SqlOnDemand", + "subnetResourceId": "", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + { + "privateDnsZoneResourceIds": [ + "" + ], + "service": "Dev", + "subnetResourceId": "" } ] }, @@ -1063,7 +1125,7 @@ Configuration details for private endpoints. For security reasons, it is recomme | Parameter | Type | Description | | :-- | :-- | :-- | -| [`service`](#parameter-privateendpointsservice) | string | The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". | +| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file". | | [`subnetResourceId`](#parameter-privateendpointssubnetresourceid) | string | Resource ID of the subnet where the endpoint needs to be created. | **Optional parameters** @@ -1075,9 +1137,10 @@ Configuration details for private endpoints. For security reasons, it is recomme | [`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. | +| [`isManualConnection`](#parameter-privateendpointsismanualconnection) | bool | If Manual Private Link Connection is required. | | [`location`](#parameter-privateendpointslocation) | string | The location to deploy the private endpoint to. | | [`lock`](#parameter-privateendpointslock) | object | Specify the type of lock. | -| [`manualPrivateLinkServiceConnections`](#parameter-privateendpointsmanualprivatelinkserviceconnections) | array | Manual PrivateLink Service Connections. | +| [`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. | @@ -1086,7 +1149,7 @@ Configuration details for private endpoints. For security reasons, it is recomme ### Parameter: `privateEndpoints.service` -The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". +The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file". - Required: Yes - Type: string @@ -1116,19 +1179,19 @@ 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. | +| [`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. +Fqdn that resolves to private endpoint IP address. - Required: No - Type: string ### 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 @@ -1181,7 +1244,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` @@ -1199,11 +1262,18 @@ 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 +### Parameter: `privateEndpoints.isManualConnection` + +If Manual Private Link Connection is required. + +- Required: No +- Type: bool + ### Parameter: `privateEndpoints.location` The location to deploy the private endpoint to. @@ -1247,12 +1317,12 @@ Specify the name of lock. - Required: No - Type: string -### Parameter: `privateEndpoints.manualPrivateLinkServiceConnections` +### Parameter: `privateEndpoints.manualConnectionRequestMessage` -Manual PrivateLink Service Connections. +A message passed to the owner of the remote resource with the manual connection request. - Required: No -- Type: array +- Type: string ### Parameter: `privateEndpoints.name` @@ -1524,7 +1594,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.3.1` | Remote reference | +| `br/public:avm/res/network/private-endpoint:0.4.0` | Remote reference | ## Data Collection diff --git a/avm/res/synapse/workspace/main.bicep b/avm/res/synapse/workspace/main.bicep index d54a6fa3c5..13c505992a 100644 --- a/avm/res/synapse/workspace/main.bicep +++ b/avm/res/synapse/workspace/main.bicep @@ -254,34 +254,45 @@ resource workspace_roleAssignments 'Microsoft.Authorization/roleAssignments@2022 }] // Endpoints -module workspace_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.3.1' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { +module workspace_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { name: '${uniqueString(deployment().name, location)}-workspace-PrivateEndpoint-${index}' params: { - privateLinkServiceConnections: [ + name: privateEndpoint.?name ?? 'pep-${last(split(workspace.id, '/'))}-${privateEndpoint.service}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ { - name: name + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(workspace.id, '/'))}-${privateEndpoint.service}-${index}' properties: { privateLinkServiceId: workspace.id groupIds: [ - privateEndpoint.?service ?? 'SQL' + privateEndpoint.service ] } } - ] - name: privateEndpoint.?name ?? 'pep-${last(split(workspace.id, '/'))}-${privateEndpoint.?service ?? privateEndpoint.service}-${index}' + ] : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(workspace.id, '/'))}-${privateEndpoint.service}-${index}' + properties: { + privateLinkServiceId: workspace.id + groupIds: [ + privateEndpoint.service + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } + ] : null subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location lock: privateEndpoint.?lock ?? lock privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds roleAssignments: privateEndpoint.?roleAssignments tags: privateEndpoint.?tags ?? tags - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections customDnsConfigs: privateEndpoint.?customDnsConfigs ipConfigurations: privateEndpoint.?ipConfigurations applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry } }] @@ -370,7 +381,7 @@ type privateEndpointType = { @description('Optional. The location to deploy the private endpoint to.') location: string? - @description('Required. The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob".') + @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.') @@ -382,12 +393,19 @@ type privateEndpointType = { @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.') + @description('Required. Fqdn that resolves to private endpoint IP address.') fqdn: string? - @description('Required. A list of private ip addresses of the private endpoint.') + @description('Required. A list of private IP addresses of the private endpoint.') ipAddresses: string[] }[]? @@ -404,7 +422,7 @@ type privateEndpointType = { @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.') + @description('Required. A private IP address obtained from the private endpoint\'s subnet.') privateIPAddress: string } }[]? @@ -424,9 +442,6 @@ type privateEndpointType = { @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') tags: object? - @description('Optional. Manual PrivateLink Service Connections.') - manualPrivateLinkServiceConnections: array? - @description('Optional. Enable/Disable usage telemetry for module.') enableTelemetry: bool? }[]? diff --git a/avm/res/synapse/workspace/main.json b/avm/res/synapse/workspace/main.json index c12bb64271..102e84b052 100644 --- a/avm/res/synapse/workspace/main.json +++ b/avm/res/synapse/workspace/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "2846633042311760037" + "templateHash": "199483993688319459" }, "name": "Synapse Workspaces", "description": "This module deploys a Synapse Workspace.", @@ -141,7 +141,7 @@ "service": { "type": "string", "metadata": { - "description": "Required. The service (sub-) type to deploy the private endpoint for. For example \"vault\" or \"blob\"." + "description": "Required. The subresource to deploy the private endpoint for. For example \"blob\", \"table\", \"queue\" or \"file\"." } }, "subnetResourceId": { @@ -167,6 +167,21 @@ "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": { @@ -176,7 +191,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint ip address." + "description": "Required. Fqdn that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -185,7 +200,7 @@ "type": "string" }, "metadata": { - "description": "Required. A list of private ip addresses of the private endpoint." + "description": "Required. A list of private IP addresses of the private endpoint." } } } @@ -224,7 +239,7 @@ "privateIPAddress": { "type": "string", "metadata": { - "description": "Required. A private ip address obtained from the private endpoint's subnet." + "description": "Required. A private IP address obtained from the private endpoint's subnet." } } }, @@ -275,13 +290,6 @@ "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." } }, - "manualPrivateLinkServiceConnections": { - "type": "array", - "nullable": true, - "metadata": { - "description": "Optional. Manual PrivateLink Service Connections." - } - }, "enableTelemetry": { "type": "bool", "nullable": true, @@ -1064,25 +1072,17 @@ }, "mode": "Incremental", "parameters": { - "privateLinkServiceConnections": { - "value": [ - { - "name": "[parameters('name')]", - "properties": { - "privateLinkServiceId": "[resourceId('Microsoft.Synapse/workspaces', parameters('name'))]", - "groupIds": [ - "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'SQL')]" - ] - } - } - ] - }, "name": { - "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.Synapse/workspaces', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service), copyIndex()))]" + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.Synapse/workspaces', parameters('name')), '/')), coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service, copyIndex()))]" }, + "privateLinkServiceConnections": "[if(not(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections'), true())), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.Synapse/workspaces', parameters('name')), '/')), coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service, copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.Synapse/workspaces', parameters('name')), 'groupIds', createArray(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service))))), createObject('value', null()))]", + "manualPrivateLinkServiceConnections": "[if(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections'), true()), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.Synapse/workspaces', parameters('name')), '/')), coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service, copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.Synapse/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)]" }, @@ -1101,9 +1101,6 @@ "tags": { "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" }, - "manualPrivateLinkServiceConnections": { - "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections')]" - }, "customDnsConfigs": { "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customDnsConfigs')]" }, @@ -1115,9 +1112,6 @@ }, "customNetworkInterfaceName": { "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customNetworkInterfaceName')]" - }, - "enableTelemetry": { - "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'enableTelemetry'), parameters('enableTelemetry'))]" } }, "template": { @@ -1127,8 +1121,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "2821141217598568122" + "version": "0.24.24.22086", + "templateHash": "2592884001616184297" }, "name": "Private Endpoints", "description": "This module deploys a Private Endpoint.", @@ -1177,7 +1171,7 @@ "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\"" + "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": { @@ -1255,7 +1249,7 @@ "privateIPAddress": { "type": "string", "metadata": { - "description": "Required. A private ip address obtained from the private endpoint's subnet." + "description": "Required. A private IP address obtained from the private endpoint's subnet." } } }, @@ -1358,7 +1352,7 @@ "fqdn": { "type": "string", "metadata": { - "description": "Required. Fqdn that resolves to private endpoint ip address." + "description": "Required. Fqdn that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -1367,7 +1361,7 @@ "type": "string" }, "metadata": { - "description": "Required. A list of private ip addresses of the private endpoint." + "description": "Required. A list of private IP addresses of the private endpoint." } } } @@ -1493,7 +1487,7 @@ "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.3.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.4.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -1598,8 +1592,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "18168683629401652671" + "version": "0.24.24.22086", + "templateHash": "9321937464667207030" }, "name": "Private Endpoint Private DNS Zone Groups", "description": "This module deploys a Private Endpoint Private DNS Zone Group.", @@ -1710,6 +1704,13 @@ "description": "The location the resource was deployed into." }, "value": "[reference('privateEndpoint', '2023-04-01', 'full').location]" + }, + "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])]" } } } diff --git a/avm/res/synapse/workspace/tests/e2e/defaults/main.test.bicep b/avm/res/synapse/workspace/tests/e2e/defaults/main.test.bicep index 30ec5ae1be..5b96756401 100644 --- a/avm/res/synapse/workspace/tests/e2e/defaults/main.test.bicep +++ b/avm/res/synapse/workspace/tests/e2e/defaults/main.test.bicep @@ -55,4 +55,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' defaultDataLakeStorageFilesystem: nestedDependencies.outputs.storageContainerName sqlAdministratorLogin: 'synwsadmin' } + dependsOn: [ + nestedDependencies + ] }] diff --git a/avm/res/synapse/workspace/tests/e2e/encrwsai/main.test.bicep b/avm/res/synapse/workspace/tests/e2e/encrwsai/main.test.bicep index 3f52c9ae3a..1099ded9b2 100644 --- a/avm/res/synapse/workspace/tests/e2e/encrwsai/main.test.bicep +++ b/avm/res/synapse/workspace/tests/e2e/encrwsai/main.test.bicep @@ -3,7 +3,6 @@ targetScope = 'subscription' metadata name = 'Using encryption with Customer-Managed-Key' metadata description = 'This instance deploys the module using Customer-Managed-Keys using a System-Assigned Identity to access the Customer-Managed-Key secret.' - // ========== // // Parameters // // ========== // @@ -66,4 +65,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' encryptionActivateWorkspace: true location: resourceLocation } + dependsOn: [ + nestedDependencies + ] }] diff --git a/avm/res/synapse/workspace/tests/e2e/encrwuai/main.test.bicep b/avm/res/synapse/workspace/tests/e2e/encrwuai/main.test.bicep index 79a8fdebb3..b1905e7fd0 100644 --- a/avm/res/synapse/workspace/tests/e2e/encrwuai/main.test.bicep +++ b/avm/res/synapse/workspace/tests/e2e/encrwuai/main.test.bicep @@ -66,4 +66,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' userAssignedIdentityResourceId: nestedDependencies.outputs.managedIdentityResourceId } } + dependsOn: [ + nestedDependencies + ] }] diff --git a/avm/res/synapse/workspace/tests/e2e/managedvnet/main.test.bicep b/avm/res/synapse/workspace/tests/e2e/managedvnet/main.test.bicep index 80e9d4ebdb..4cbe44aa95 100644 --- a/avm/res/synapse/workspace/tests/e2e/managedvnet/main.test.bicep +++ b/avm/res/synapse/workspace/tests/e2e/managedvnet/main.test.bicep @@ -3,7 +3,6 @@ targetScope = 'subscription' metadata name = 'Using managed Vnet' metadata description = 'This instance deploys the module using a managed Vnet.' - // ========== // // Parameters // // ========== // @@ -61,4 +60,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' tenant().tenantId ] } + dependsOn: [ + nestedDependencies + ] }] diff --git a/avm/res/synapse/workspace/tests/e2e/max/dependencies.bicep b/avm/res/synapse/workspace/tests/e2e/max/dependencies.bicep index 52da267176..b237c382f6 100644 --- a/avm/res/synapse/workspace/tests/e2e/max/dependencies.bicep +++ b/avm/res/synapse/workspace/tests/e2e/max/dependencies.bicep @@ -30,7 +30,19 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { { name: 'defaultSubnet' properties: { - addressPrefix: cidrSubnet(addressPrefix, 16, 0) + addressPrefix: cidrSubnet(addressPrefix, 20, 0) + } + } + { + name: 'custom-private-subnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 20, 1) + } + } + { + name: 'custom-private-subnet-2' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 20, 2) } } ] @@ -79,8 +91,14 @@ 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 Virtual Network Subnet.') -output subnetResourceId string = virtualNetwork.properties.subnets[0].id +@description('The resource ID of the created Virtual Network Default Subnet.') +output defaultSubnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The resource ID of the 2nd created Virtual Network Subnet.') +output customSubnet1ResourceId string = virtualNetwork.properties.subnets[1].id + +@description('The resource ID of the 3rd created Virtual Network Subnet.') +output customSubnet2ResourceId string = virtualNetwork.properties.subnets[2].id @description('The resource ID of the created Private DNS Zone.') output privateDNSZoneResourceId string = privateDNSZone.id diff --git a/avm/res/synapse/workspace/tests/e2e/max/main.test.bicep b/avm/res/synapse/workspace/tests/e2e/max/main.test.bicep index 623225fb1d..b798023efb 100644 --- a/avm/res/synapse/workspace/tests/e2e/max/main.test.bicep +++ b/avm/res/synapse/workspace/tests/e2e/max/main.test.bicep @@ -99,13 +99,44 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' nestedDependencies.outputs.privateDNSZoneResourceId ] service: 'SQL' - subnetResourceId: nestedDependencies.outputs.subnetResourceId + subnetResourceId: nestedDependencies.outputs.customSubnet1ResourceId tags: { 'hidden-title': 'This is visible in the resource name' Environment: 'Non-Prod' Role: 'DeploymentValidation' } } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + service: 'SQL' + subnetResourceId: nestedDependencies.outputs.customSubnet2ResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + service: 'SqlOnDemand' + subnetResourceId: nestedDependencies.outputs.customSubnet1ResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + service: 'Dev' + subnetResourceId: nestedDependencies.outputs.customSubnet1ResourceId + } ] managedVirtualNetwork: true integrationRuntimes: [ @@ -132,4 +163,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' } ] } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] }] diff --git a/avm/res/synapse/workspace/tests/e2e/waf-aligned/main.test.bicep b/avm/res/synapse/workspace/tests/e2e/waf-aligned/main.test.bicep index 8eed631785..f47275aa9e 100644 --- a/avm/res/synapse/workspace/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/synapse/workspace/tests/e2e/waf-aligned/main.test.bicep @@ -113,4 +113,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' Role: 'DeploymentValidation' } } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] }] diff --git a/avm/res/synapse/workspace/version.json b/avm/res/synapse/workspace/version.json index 83083db694..c177b1bb58 100644 --- a/avm/res/synapse/workspace/version.json +++ b/avm/res/synapse/workspace/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.1", + "version": "0.3", "pathFilters": [ "./main.json" ] From e53c0369ea43e08229ff8992874fb4965f421b08 Mon Sep 17 00:00:00 2001 From: Alexander Ojala Date: Tue, 19 Mar 2024 23:59:05 +0100 Subject: [PATCH 42/73] feat: New module `avm/res/recovery-services/vault` (#1216) ## Description New Module `avm/res/recovery-services/vault`, migrated from CARML. ## Adding a new module - [ ] A proposal has been submitted and approved. - [ ] I have included "Closes #{module_proposal_issue_number}" in the PR description. - [ ] I have run `brm validate` locally to verify the module files. - [ ] I have run deployment tests locally to ensure the module is deployable. ## Pipeline references | Pipeline | | - | | [![avm.res.recovery-services.vault](https://github.com/alexanderojala/bicep-registry-modules/actions/workflows/avm.res.recovery-services.vault.yml/badge.svg?branch=alexanderojala_recoveryservicevault)](https://github.com/alexanderojala/bicep-registry-modules/actions/workflows/avm.res.recovery-services.vault.yml) | --------- Co-authored-by: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> --- .github/CODEOWNERS | 2 +- .github/ISSUE_TEMPLATE/avm_module_issue.yml | 2 +- .../avm.res.recovery-services.vault.yml | 85 + avm/res/recovery-services/vault/README.md | 2654 ++++++++++++++++ .../vault/backup-config/README.md | 165 + .../vault/backup-config/main.bicep | 81 + .../vault/backup-config/main.json | 141 + .../protection-container/README.md | 146 + .../protection-container/main.bicep | 81 + .../protection-container/main.json | 277 ++ .../protected-item/README.md | 123 + .../protected-item/main.bicep | 55 + .../protected-item/main.json | 107 + .../vault/backup-policy/README.md | 70 + .../vault/backup-policy/main.bicep | 31 + .../vault/backup-policy/main.json | 65 + .../vault/backup-storage-config/README.md | 90 + .../vault/backup-storage-config/main.bicep | 43 + .../vault/backup-storage-config/main.json | 83 + avm/res/recovery-services/vault/main.bicep | 453 +++ avm/res/recovery-services/vault/main.json | 2702 +++++++++++++++++ .../vault/replication-alert-setting/README.md | 97 + .../replication-alert-setting/main.bicep | 45 + .../vault/replication-alert-setting/main.json | 89 + .../vault/replication-fabric/README.md | 90 + .../vault/replication-fabric/main.bicep | 49 + .../vault/replication-fabric/main.json | 340 +++ .../README.md | 87 + .../main.bicep | 55 + .../main.json | 231 ++ .../README.md | 126 + .../main.bicep | 56 + .../main.json | 118 + .../vault/replication-policy/README.md | 112 + .../vault/replication-policy/main.bicep | 48 + .../vault/replication-policy/main.json | 99 + .../vault/tests/e2e/defaults/main.test.bicep | 62 + .../vault/tests/e2e/dr/main.test.bicep | 110 + .../vault/tests/e2e/max/dependencies.bicep | 63 + .../vault/tests/e2e/max/main.test.bicep | 433 +++ .../tests/e2e/waf-aligned/dependencies.bicep | 63 + .../tests/e2e/waf-aligned/main.test.bicep | 416 +++ avm/res/recovery-services/vault/version.json | 7 + 43 files changed, 10250 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/avm.res.recovery-services.vault.yml create mode 100644 avm/res/recovery-services/vault/README.md create mode 100644 avm/res/recovery-services/vault/backup-config/README.md create mode 100644 avm/res/recovery-services/vault/backup-config/main.bicep create mode 100644 avm/res/recovery-services/vault/backup-config/main.json create mode 100644 avm/res/recovery-services/vault/backup-fabric/protection-container/README.md create mode 100644 avm/res/recovery-services/vault/backup-fabric/protection-container/main.bicep create mode 100644 avm/res/recovery-services/vault/backup-fabric/protection-container/main.json create mode 100644 avm/res/recovery-services/vault/backup-fabric/protection-container/protected-item/README.md create mode 100644 avm/res/recovery-services/vault/backup-fabric/protection-container/protected-item/main.bicep create mode 100644 avm/res/recovery-services/vault/backup-fabric/protection-container/protected-item/main.json create mode 100644 avm/res/recovery-services/vault/backup-policy/README.md create mode 100644 avm/res/recovery-services/vault/backup-policy/main.bicep create mode 100644 avm/res/recovery-services/vault/backup-policy/main.json create mode 100644 avm/res/recovery-services/vault/backup-storage-config/README.md create mode 100644 avm/res/recovery-services/vault/backup-storage-config/main.bicep create mode 100644 avm/res/recovery-services/vault/backup-storage-config/main.json create mode 100644 avm/res/recovery-services/vault/main.bicep create mode 100644 avm/res/recovery-services/vault/main.json create mode 100644 avm/res/recovery-services/vault/replication-alert-setting/README.md create mode 100644 avm/res/recovery-services/vault/replication-alert-setting/main.bicep create mode 100644 avm/res/recovery-services/vault/replication-alert-setting/main.json create mode 100644 avm/res/recovery-services/vault/replication-fabric/README.md create mode 100644 avm/res/recovery-services/vault/replication-fabric/main.bicep create mode 100644 avm/res/recovery-services/vault/replication-fabric/main.json create mode 100644 avm/res/recovery-services/vault/replication-fabric/replication-protection-container/README.md create mode 100644 avm/res/recovery-services/vault/replication-fabric/replication-protection-container/main.bicep create mode 100644 avm/res/recovery-services/vault/replication-fabric/replication-protection-container/main.json create mode 100644 avm/res/recovery-services/vault/replication-fabric/replication-protection-container/replication-protection-container-mapping/README.md create mode 100644 avm/res/recovery-services/vault/replication-fabric/replication-protection-container/replication-protection-container-mapping/main.bicep create mode 100644 avm/res/recovery-services/vault/replication-fabric/replication-protection-container/replication-protection-container-mapping/main.json create mode 100644 avm/res/recovery-services/vault/replication-policy/README.md create mode 100644 avm/res/recovery-services/vault/replication-policy/main.bicep create mode 100644 avm/res/recovery-services/vault/replication-policy/main.json create mode 100644 avm/res/recovery-services/vault/tests/e2e/defaults/main.test.bicep create mode 100644 avm/res/recovery-services/vault/tests/e2e/dr/main.test.bicep create mode 100644 avm/res/recovery-services/vault/tests/e2e/max/dependencies.bicep create mode 100644 avm/res/recovery-services/vault/tests/e2e/max/main.test.bicep create mode 100644 avm/res/recovery-services/vault/tests/e2e/waf-aligned/dependencies.bicep create mode 100644 avm/res/recovery-services/vault/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/res/recovery-services/vault/version.json diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 99557d99bb..335d7842a5 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -118,7 +118,7 @@ #/avm/res/policy-insights/remediation/ @Azure/avm-res-policyinsights-remediation-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/power-bi-dedicated/capacity/ @Azure/avm-res-powerbidedicated-capacity-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/purview/account/ @Azure/avm-res-purview-account-module-owners-bicep @Azure/avm-core-team-technical-bicep -#/avm/res/recovery-services/vault/ @Azure/avm-res-recoveryservices-vault-module-owners-bicep @Azure/avm-core-team-technical-bicep +/avm/res/recovery-services/vault/ @Azure/avm-res-recoveryservices-vault-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/relay/namespace/ @Azure/avm-res-relay-namespace-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/resource-graph/query/ @Azure/avm-res-resourcegraph-query-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/resources/deployment-script/ @Azure/avm-res-resources-deploymentscript-module-owners-bicep @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 69b3fd5b21..37fbffc58f 100644 --- a/.github/ISSUE_TEMPLATE/avm_module_issue.yml +++ b/.github/ISSUE_TEMPLATE/avm_module_issue.yml @@ -152,7 +152,7 @@ body: # - "avm/res/policy-insights/remediation" - "avm/res/power-bi-dedicated/capacity" - "avm/res/purview/account" - # - "avm/res/recovery-services/vault" + - "avm/res/recovery-services/vault" # - "avm/res/relay/namespace" - "avm/res/resource-graph/query" - "avm/res/resources/deployment-script" diff --git a/.github/workflows/avm.res.recovery-services.vault.yml b/.github/workflows/avm.res.recovery-services.vault.yml new file mode 100644 index 0000000000..bc630cebbc --- /dev/null +++ b/.github/workflows/avm.res.recovery-services.vault.yml @@ -0,0 +1,85 @@ +name: "avm.res.recovery-services.vault" + +on: + schedule: + - cron: "0 12 1/15 * *" # Bi-Weekly Test (on 1st & 15th of month) + 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 + push: + branches: + - main + paths: + - ".github/actions/templates/avm-**" + - ".github/workflows/avm.template.module.yml" + - ".github/workflows/avm.res.recovery-services.vault.yml" + - "avm/res/recovery-services/vault/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/recovery-services/vault" + workflowPath: ".github/workflows/avm.res.recovery-services.vault.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-latest + name: "Initialize pipeline" + steps: + - name: "Checkout" + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: "Set input parameters to output variables" + id: get-workflow-param + uses: ./.github/actions/templates/avm-getWorkflowInput + with: + workflowPath: "${{ env.workflowPath}}" + - name: "Get module test file paths" + id: get-module-test-file-paths + uses: ./.github/actions/templates/avm-getModuleTestFiles + with: + modulePath: "${{ env.modulePath }}" + outputs: + workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }} + moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} + psRuleModuleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.psRuleModuleTestFilePaths }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Run" + permissions: + id-token: write # For OIDC + contents: write # For release tags + needs: + - job_initialize_pipeline + uses: ./.github/workflows/avm.template.module.yml + with: + workflowInput: "${{ needs.job_initialize_pipeline.outputs.workflowInput }}" + moduleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.moduleTestFilePaths }}" + psRuleModuleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.psRuleModuleTestFilePaths }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit diff --git a/avm/res/recovery-services/vault/README.md b/avm/res/recovery-services/vault/README.md new file mode 100644 index 0000000000..fcba17825f --- /dev/null +++ b/avm/res/recovery-services/vault/README.md @@ -0,0 +1,2654 @@ +# Recovery Services Vaults `[Microsoft.RecoveryServices/vaults]` + +This module deploys a Recovery Services Vault. + +## Navigation + +- [Resource Types](#Resource-Types) +- [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` | [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/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.RecoveryServices/vaults` | [2023-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2023-01-01/vaults) | +| `Microsoft.RecoveryServices/vaults/backupconfig` | [2023-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2023-01-01/vaults/backupconfig) | +| `Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers` | [2023-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2023-01-01/vaults/backupFabrics/protectionContainers) | +| `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.RecoveryServices/vaults/backupPolicies` | [2023-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2023-01-01/vaults/backupPolicies) | +| `Microsoft.RecoveryServices/vaults/backupstorageconfig` | [2023-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2023-01-01/vaults/backupstorageconfig) | +| `Microsoft.RecoveryServices/vaults/replicationAlertSettings` | [2022-10-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2022-10-01/vaults/replicationAlertSettings) | +| `Microsoft.RecoveryServices/vaults/replicationFabrics` | [2022-10-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2022-10-01/vaults/replicationFabrics) | +| `Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers` | [2022-10-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2022-10-01/vaults/replicationFabrics/replicationProtectionContainers) | +| `Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings` | [2022-10-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2022-10-01/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings) | +| `Microsoft.RecoveryServices/vaults/replicationPolicies` | [2023-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/vaults/replicationPolicies) | + +## 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/res/recovery-services/vault:`. + +- [Using only defaults](#example-1-using-only-defaults) +- [Test case for disaster recovery enabled](#example-2-test-case-for-disaster-recovery-enabled) +- [Using large parameter set](#example-3-using-large-parameter-set) +- [WAF-aligned](#example-4-waf-aligned) + +### Example 1: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. + + +
+ +via Bicep module + +```bicep +module vault 'br/public:avm/res/recovery-services/vault:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-rsvmin' + params: { + // Required parameters + name: 'rsvmin001' + // Non-required parameters + enableTelemetry: '' + location: '' + replicationAlertSettings: { + customEmailAddresses: [ + 'test.user@testcompany.com' + ] + locale: 'en-US' + sendToOwners: 'Send' + } + securitySettings: { + immutabilitySettings: { + state: 'Unlocked' + } + } + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "rsvmin001" + }, + // Non-required parameters + "enableTelemetry": { + "value": "" + }, + "location": { + "value": "" + }, + "replicationAlertSettings": { + "value": { + "customEmailAddresses": [ + "test.user@testcompany.com" + ], + "locale": "en-US", + "sendToOwners": "Send" + } + }, + "securitySettings": { + "value": { + "immutabilitySettings": { + "state": "Unlocked" + } + } + } + } +} +``` + +
+

+ +### Example 2: _Test case for disaster recovery enabled_ + +This instance deploys the module with disaster recovery enabled. + + +

+ +via Bicep module + +```bicep +module vault 'br/public:avm/res/recovery-services/vault:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-rsvdr' + params: { + // Required parameters + name: '' + // Non-required parameters + enableTelemetry: '' + location: '' + replicationFabrics: [ + { + location: 'NorthEurope' + replicationContainers: [ + { + name: 'ne-container1' + replicationContainerMappings: [ + { + policyName: 'Default_values' + targetContainerName: 'pluto' + targetProtectionContainerId: '' + } + ] + } + { + name: 'ne-container2' + replicationContainerMappings: [ + { + policyName: 'Default_values' + targetContainerFabricName: 'WE-2' + targetContainerName: 'we-container1' + } + ] + } + ] + } + { + location: 'WestEurope' + name: 'WE-2' + replicationContainers: [ + { + name: 'we-container1' + replicationContainerMappings: [ + { + policyName: 'Default_values' + targetContainerFabricName: 'NorthEurope' + targetContainerName: 'ne-container2' + } + ] + } + ] + } + ] + replicationPolicies: [ + { + name: 'Default_values' + } + { + appConsistentFrequencyInMinutes: 240 + crashConsistentFrequencyInMinutes: 7 + multiVmSyncStatus: 'Disable' + name: 'Custom_values' + recoveryPointHistory: 2880 + } + ] + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "" + }, + // Non-required parameters + "enableTelemetry": { + "value": "" + }, + "location": { + "value": "" + }, + "replicationFabrics": { + "value": [ + { + "location": "NorthEurope", + "replicationContainers": [ + { + "name": "ne-container1", + "replicationContainerMappings": [ + { + "policyName": "Default_values", + "targetContainerName": "pluto", + "targetProtectionContainerId": "" + } + ] + }, + { + "name": "ne-container2", + "replicationContainerMappings": [ + { + "policyName": "Default_values", + "targetContainerFabricName": "WE-2", + "targetContainerName": "we-container1" + } + ] + } + ] + }, + { + "location": "WestEurope", + "name": "WE-2", + "replicationContainers": [ + { + "name": "we-container1", + "replicationContainerMappings": [ + { + "policyName": "Default_values", + "targetContainerFabricName": "NorthEurope", + "targetContainerName": "ne-container2" + } + ] + } + ] + } + ] + }, + "replicationPolicies": { + "value": [ + { + "name": "Default_values" + }, + { + "appConsistentFrequencyInMinutes": 240, + "crashConsistentFrequencyInMinutes": 7, + "multiVmSyncStatus": "Disable", + "name": "Custom_values", + "recoveryPointHistory": 2880 + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module vault 'br/public:avm/res/recovery-services/vault:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-rsvmax' + params: { + // Required parameters + name: 'rsvmax001' + // Non-required parameters + backupConfig: { + enhancedSecurityState: 'Disabled' + softDeleteFeatureState: 'Disabled' + } + backupPolicies: [ + { + name: 'VMpolicy' + properties: { + backupManagementType: 'AzureIaasVM' + instantRPDetails: {} + instantRpRetentionRangeInDays: 2 + protectedItemsCount: 0 + retentionPolicy: { + dailySchedule: { + retentionDuration: { + count: 180 + durationType: 'Days' + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + } + monthlySchedule: { + retentionDuration: { + count: 60 + durationType: 'Months' + } + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + } + retentionPolicyType: 'LongTermRetentionPolicy' + weeklySchedule: { + daysOfTheWeek: [ + 'Sunday' + ] + retentionDuration: { + count: 12 + durationType: 'Weeks' + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + } + yearlySchedule: { + monthsOfYear: [ + 'January' + ] + retentionDuration: { + count: 10 + durationType: 'Years' + } + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + } + } + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunFrequency: 'Daily' + scheduleRunTimes: [ + '2019-11-07T07:00:00Z' + ] + scheduleWeeklyFrequency: 0 + } + timeZone: 'UTC' + } + } + { + name: 'sqlpolicy' + properties: { + backupManagementType: 'AzureWorkload' + protectedItemsCount: 0 + settings: { + isCompression: true + issqlcompression: true + timeZone: 'UTC' + } + subProtectionPolicy: [ + { + policyType: 'Full' + retentionPolicy: { + monthlySchedule: { + retentionDuration: { + count: 60 + durationType: 'Months' + } + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T22:00:00Z' + ] + } + retentionPolicyType: 'LongTermRetentionPolicy' + weeklySchedule: { + daysOfTheWeek: [ + 'Sunday' + ] + retentionDuration: { + count: 104 + durationType: 'Weeks' + } + retentionTimes: [ + '2019-11-07T22:00:00Z' + ] + } + yearlySchedule: { + monthsOfYear: [ + 'January' + ] + retentionDuration: { + count: 10 + durationType: 'Years' + } + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T22:00:00Z' + ] + } + } + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunDays: [ + 'Sunday' + ] + scheduleRunFrequency: 'Weekly' + scheduleRunTimes: [ + '2019-11-07T22:00:00Z' + ] + scheduleWeeklyFrequency: 0 + } + } + { + policyType: 'Differential' + retentionPolicy: { + retentionDuration: { + count: 30 + durationType: 'Days' + } + retentionPolicyType: 'SimpleRetentionPolicy' + } + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunDays: [ + 'Monday' + ] + scheduleRunFrequency: 'Weekly' + scheduleRunTimes: [ + '2017-03-07T02:00:00Z' + ] + scheduleWeeklyFrequency: 0 + } + } + { + policyType: 'Log' + retentionPolicy: { + retentionDuration: { + count: 15 + durationType: 'Days' + } + retentionPolicyType: 'SimpleRetentionPolicy' + } + schedulePolicy: { + scheduleFrequencyInMins: 120 + schedulePolicyType: 'LogSchedulePolicy' + } + } + ] + workLoadType: 'SQLDataBase' + } + } + { + name: 'filesharepolicy' + properties: { + backupManagementType: 'AzureStorage' + protectedItemsCount: 0 + retentionPolicy: { + dailySchedule: { + retentionDuration: { + count: 30 + durationType: 'Days' + } + retentionTimes: [ + '2019-11-07T04:30:00Z' + ] + } + retentionPolicyType: 'LongTermRetentionPolicy' + } + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunFrequency: 'Daily' + scheduleRunTimes: [ + '2019-11-07T04:30:00Z' + ] + scheduleWeeklyFrequency: 0 + } + timeZone: 'UTC' + workloadType: 'AzureFileShare' + } + } + ] + backupStorageConfig: { + crossRegionRestoreFlag: true + storageModelType: 'GeoRedundant' + } + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + enableTelemetry: '' + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + '' + ] + } + monitoringSettings: { + azureMonitorAlertSettings: { + alertsForAllJobFailures: 'Enabled' + } + classicAlertSettings: { + alertsForCriticalOperations: 'Enabled' + } + } + privateEndpoints: [ + { + ipConfigurations: [ + { + name: 'myIpConfig-1' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-tel1' + privateIPAddress: '10.0.0.10' + } + } + { + name: 'myIPconfig-2' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-prot2' + privateIPAddress: '10.0.0.11' + } + } + { + name: 'myIPconfig-3' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-srs1' + privateIPAddress: '10.0.0.12' + } + } + { + name: 'myIPconfig-4' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-rcm1' + privateIPAddress: '10.0.0.13' + } + } + { + name: 'myIPconfig-5' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-id1' + privateIPAddress: '10.0.0.14' + } + } + ] + privateDnsZoneResourceIds: [ + '' + ] + subnetResourceId: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + ] + replicationAlertSettings: { + customEmailAddresses: [ + 'test.user@testcompany.com' + ] + locale: 'en-US' + sendToOwners: 'Send' + } + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + securitySettings: { + immutabilitySettings: { + state: 'Unlocked' + } + } + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "rsvmax001" + }, + // Non-required parameters + "backupConfig": { + "value": { + "enhancedSecurityState": "Disabled", + "softDeleteFeatureState": "Disabled" + } + }, + "backupPolicies": { + "value": [ + { + "name": "VMpolicy", + "properties": { + "backupManagementType": "AzureIaasVM", + "instantRPDetails": {}, + "instantRpRetentionRangeInDays": 2, + "protectedItemsCount": 0, + "retentionPolicy": { + "dailySchedule": { + "retentionDuration": { + "count": 180, + "durationType": "Days" + }, + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ] + }, + "monthlySchedule": { + "retentionDuration": { + "count": 60, + "durationType": "Months" + }, + "retentionScheduleFormatType": "Weekly", + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ] + }, + "retentionPolicyType": "LongTermRetentionPolicy", + "weeklySchedule": { + "daysOfTheWeek": [ + "Sunday" + ], + "retentionDuration": { + "count": 12, + "durationType": "Weeks" + }, + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ] + }, + "yearlySchedule": { + "monthsOfYear": [ + "January" + ], + "retentionDuration": { + "count": 10, + "durationType": "Years" + }, + "retentionScheduleFormatType": "Weekly", + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ] + } + }, + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunFrequency": "Daily", + "scheduleRunTimes": [ + "2019-11-07T07:00:00Z" + ], + "scheduleWeeklyFrequency": 0 + }, + "timeZone": "UTC" + } + }, + { + "name": "sqlpolicy", + "properties": { + "backupManagementType": "AzureWorkload", + "protectedItemsCount": 0, + "settings": { + "isCompression": true, + "issqlcompression": true, + "timeZone": "UTC" + }, + "subProtectionPolicy": [ + { + "policyType": "Full", + "retentionPolicy": { + "monthlySchedule": { + "retentionDuration": { + "count": 60, + "durationType": "Months" + }, + "retentionScheduleFormatType": "Weekly", + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T22:00:00Z" + ] + }, + "retentionPolicyType": "LongTermRetentionPolicy", + "weeklySchedule": { + "daysOfTheWeek": [ + "Sunday" + ], + "retentionDuration": { + "count": 104, + "durationType": "Weeks" + }, + "retentionTimes": [ + "2019-11-07T22:00:00Z" + ] + }, + "yearlySchedule": { + "monthsOfYear": [ + "January" + ], + "retentionDuration": { + "count": 10, + "durationType": "Years" + }, + "retentionScheduleFormatType": "Weekly", + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T22:00:00Z" + ] + } + }, + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunDays": [ + "Sunday" + ], + "scheduleRunFrequency": "Weekly", + "scheduleRunTimes": [ + "2019-11-07T22:00:00Z" + ], + "scheduleWeeklyFrequency": 0 + } + }, + { + "policyType": "Differential", + "retentionPolicy": { + "retentionDuration": { + "count": 30, + "durationType": "Days" + }, + "retentionPolicyType": "SimpleRetentionPolicy" + }, + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunDays": [ + "Monday" + ], + "scheduleRunFrequency": "Weekly", + "scheduleRunTimes": [ + "2017-03-07T02:00:00Z" + ], + "scheduleWeeklyFrequency": 0 + } + }, + { + "policyType": "Log", + "retentionPolicy": { + "retentionDuration": { + "count": 15, + "durationType": "Days" + }, + "retentionPolicyType": "SimpleRetentionPolicy" + }, + "schedulePolicy": { + "scheduleFrequencyInMins": 120, + "schedulePolicyType": "LogSchedulePolicy" + } + } + ], + "workLoadType": "SQLDataBase" + } + }, + { + "name": "filesharepolicy", + "properties": { + "backupManagementType": "AzureStorage", + "protectedItemsCount": 0, + "retentionPolicy": { + "dailySchedule": { + "retentionDuration": { + "count": 30, + "durationType": "Days" + }, + "retentionTimes": [ + "2019-11-07T04:30:00Z" + ] + }, + "retentionPolicyType": "LongTermRetentionPolicy" + }, + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunFrequency": "Daily", + "scheduleRunTimes": [ + "2019-11-07T04:30:00Z" + ], + "scheduleWeeklyFrequency": 0 + }, + "timeZone": "UTC", + "workloadType": "AzureFileShare" + } + } + ] + }, + "backupStorageConfig": { + "value": { + "crossRegionRestoreFlag": true, + "storageModelType": "GeoRedundant" + } + }, + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "enableTelemetry": { + "value": "" + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "managedIdentities": { + "value": { + "systemAssigned": true, + "userAssignedResourceIds": [ + "" + ] + } + }, + "monitoringSettings": { + "value": { + "azureMonitorAlertSettings": { + "alertsForAllJobFailures": "Enabled" + }, + "classicAlertSettings": { + "alertsForCriticalOperations": "Enabled" + } + } + }, + "privateEndpoints": { + "value": [ + { + "ipConfigurations": [ + { + "name": "myIpConfig-1", + "properties": { + "groupId": "AzureSiteRecovery", + "memberName": "SiteRecovery-tel1", + "privateIPAddress": "10.0.0.10" + } + }, + { + "name": "myIPconfig-2", + "properties": { + "groupId": "AzureSiteRecovery", + "memberName": "SiteRecovery-prot2", + "privateIPAddress": "10.0.0.11" + } + }, + { + "name": "myIPconfig-3", + "properties": { + "groupId": "AzureSiteRecovery", + "memberName": "SiteRecovery-srs1", + "privateIPAddress": "10.0.0.12" + } + }, + { + "name": "myIPconfig-4", + "properties": { + "groupId": "AzureSiteRecovery", + "memberName": "SiteRecovery-rcm1", + "privateIPAddress": "10.0.0.13" + } + }, + { + "name": "myIPconfig-5", + "properties": { + "groupId": "AzureSiteRecovery", + "memberName": "SiteRecovery-id1", + "privateIPAddress": "10.0.0.14" + } + } + ], + "privateDnsZoneResourceIds": [ + "" + ], + "subnetResourceId": "", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + ] + }, + "replicationAlertSettings": { + "value": { + "customEmailAddresses": [ + "test.user@testcompany.com" + ], + "locale": "en-US", + "sendToOwners": "Send" + } + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "securitySettings": { + "value": { + "immutabilitySettings": { + "state": "Unlocked" + } + } + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module vault 'br/public:avm/res/recovery-services/vault:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-rsvwaf' + params: { + // Required parameters + name: 'rsvwaf001' + // Non-required parameters + backupConfig: { + enhancedSecurityState: 'Disabled' + softDeleteFeatureState: 'Disabled' + } + backupPolicies: [ + { + name: 'VMpolicy' + properties: { + backupManagementType: 'AzureIaasVM' + instantRPDetails: {} + instantRpRetentionRangeInDays: 2 + protectedItemsCount: 0 + retentionPolicy: { + dailySchedule: { + retentionDuration: { + count: 180 + durationType: 'Days' + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + } + monthlySchedule: { + retentionDuration: { + count: 60 + durationType: 'Months' + } + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + } + retentionPolicyType: 'LongTermRetentionPolicy' + weeklySchedule: { + daysOfTheWeek: [ + 'Sunday' + ] + retentionDuration: { + count: 12 + durationType: 'Weeks' + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + } + yearlySchedule: { + monthsOfYear: [ + 'January' + ] + retentionDuration: { + count: 10 + durationType: 'Years' + } + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + } + } + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunFrequency: 'Daily' + scheduleRunTimes: [ + '2019-11-07T07:00:00Z' + ] + scheduleWeeklyFrequency: 0 + } + timeZone: 'UTC' + } + } + { + name: 'sqlpolicy' + properties: { + backupManagementType: 'AzureWorkload' + protectedItemsCount: 0 + settings: { + isCompression: true + issqlcompression: true + timeZone: 'UTC' + } + subProtectionPolicy: [ + { + policyType: 'Full' + retentionPolicy: { + monthlySchedule: { + retentionDuration: { + count: 60 + durationType: 'Months' + } + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T22:00:00Z' + ] + } + retentionPolicyType: 'LongTermRetentionPolicy' + weeklySchedule: { + daysOfTheWeek: [ + 'Sunday' + ] + retentionDuration: { + count: 104 + durationType: 'Weeks' + } + retentionTimes: [ + '2019-11-07T22:00:00Z' + ] + } + yearlySchedule: { + monthsOfYear: [ + 'January' + ] + retentionDuration: { + count: 10 + durationType: 'Years' + } + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T22:00:00Z' + ] + } + } + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunDays: [ + 'Sunday' + ] + scheduleRunFrequency: 'Weekly' + scheduleRunTimes: [ + '2019-11-07T22:00:00Z' + ] + scheduleWeeklyFrequency: 0 + } + } + { + policyType: 'Differential' + retentionPolicy: { + retentionDuration: { + count: 30 + durationType: 'Days' + } + retentionPolicyType: 'SimpleRetentionPolicy' + } + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunDays: [ + 'Monday' + ] + scheduleRunFrequency: 'Weekly' + scheduleRunTimes: [ + '2017-03-07T02:00:00Z' + ] + scheduleWeeklyFrequency: 0 + } + } + { + policyType: 'Log' + retentionPolicy: { + retentionDuration: { + count: 15 + durationType: 'Days' + } + retentionPolicyType: 'SimpleRetentionPolicy' + } + schedulePolicy: { + scheduleFrequencyInMins: 120 + schedulePolicyType: 'LogSchedulePolicy' + } + } + ] + workLoadType: 'SQLDataBase' + } + } + { + name: 'filesharepolicy' + properties: { + backupManagementType: 'AzureStorage' + protectedItemsCount: 0 + retentionPolicy: { + dailySchedule: { + retentionDuration: { + count: 30 + durationType: 'Days' + } + retentionTimes: [ + '2019-11-07T04:30:00Z' + ] + } + retentionPolicyType: 'LongTermRetentionPolicy' + } + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunFrequency: 'Daily' + scheduleRunTimes: [ + '2019-11-07T04:30:00Z' + ] + scheduleWeeklyFrequency: 0 + } + timeZone: 'UTC' + workloadType: 'AzureFileShare' + } + } + ] + backupStorageConfig: { + crossRegionRestoreFlag: true + storageModelType: 'GeoRedundant' + } + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + enableTelemetry: '' + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + '' + ] + } + monitoringSettings: { + azureMonitorAlertSettings: { + alertsForAllJobFailures: 'Enabled' + } + classicAlertSettings: { + alertsForCriticalOperations: 'Enabled' + } + } + privateEndpoints: [ + { + ipConfigurations: [ + { + name: 'myIpConfig-1' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-tel1' + privateIPAddress: '10.0.0.10' + } + } + { + name: 'myIPconfig-2' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-prot2' + privateIPAddress: '10.0.0.11' + } + } + { + name: 'myIPconfig-3' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-srs1' + privateIPAddress: '10.0.0.12' + } + } + { + name: 'myIPconfig-4' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-rcm1' + privateIPAddress: '10.0.0.13' + } + } + { + name: 'myIPconfig-5' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-id1' + privateIPAddress: '10.0.0.14' + } + } + ] + privateDnsZoneResourceIds: [ + '' + ] + subnetResourceId: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + ] + replicationAlertSettings: { + customEmailAddresses: [ + 'test.user@testcompany.com' + ] + locale: 'en-US' + sendToOwners: 'Send' + } + securitySettings: { + immutabilitySettings: { + state: 'Unlocked' + } + } + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "rsvwaf001" + }, + // Non-required parameters + "backupConfig": { + "value": { + "enhancedSecurityState": "Disabled", + "softDeleteFeatureState": "Disabled" + } + }, + "backupPolicies": { + "value": [ + { + "name": "VMpolicy", + "properties": { + "backupManagementType": "AzureIaasVM", + "instantRPDetails": {}, + "instantRpRetentionRangeInDays": 2, + "protectedItemsCount": 0, + "retentionPolicy": { + "dailySchedule": { + "retentionDuration": { + "count": 180, + "durationType": "Days" + }, + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ] + }, + "monthlySchedule": { + "retentionDuration": { + "count": 60, + "durationType": "Months" + }, + "retentionScheduleFormatType": "Weekly", + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ] + }, + "retentionPolicyType": "LongTermRetentionPolicy", + "weeklySchedule": { + "daysOfTheWeek": [ + "Sunday" + ], + "retentionDuration": { + "count": 12, + "durationType": "Weeks" + }, + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ] + }, + "yearlySchedule": { + "monthsOfYear": [ + "January" + ], + "retentionDuration": { + "count": 10, + "durationType": "Years" + }, + "retentionScheduleFormatType": "Weekly", + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ] + } + }, + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunFrequency": "Daily", + "scheduleRunTimes": [ + "2019-11-07T07:00:00Z" + ], + "scheduleWeeklyFrequency": 0 + }, + "timeZone": "UTC" + } + }, + { + "name": "sqlpolicy", + "properties": { + "backupManagementType": "AzureWorkload", + "protectedItemsCount": 0, + "settings": { + "isCompression": true, + "issqlcompression": true, + "timeZone": "UTC" + }, + "subProtectionPolicy": [ + { + "policyType": "Full", + "retentionPolicy": { + "monthlySchedule": { + "retentionDuration": { + "count": 60, + "durationType": "Months" + }, + "retentionScheduleFormatType": "Weekly", + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T22:00:00Z" + ] + }, + "retentionPolicyType": "LongTermRetentionPolicy", + "weeklySchedule": { + "daysOfTheWeek": [ + "Sunday" + ], + "retentionDuration": { + "count": 104, + "durationType": "Weeks" + }, + "retentionTimes": [ + "2019-11-07T22:00:00Z" + ] + }, + "yearlySchedule": { + "monthsOfYear": [ + "January" + ], + "retentionDuration": { + "count": 10, + "durationType": "Years" + }, + "retentionScheduleFormatType": "Weekly", + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T22:00:00Z" + ] + } + }, + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunDays": [ + "Sunday" + ], + "scheduleRunFrequency": "Weekly", + "scheduleRunTimes": [ + "2019-11-07T22:00:00Z" + ], + "scheduleWeeklyFrequency": 0 + } + }, + { + "policyType": "Differential", + "retentionPolicy": { + "retentionDuration": { + "count": 30, + "durationType": "Days" + }, + "retentionPolicyType": "SimpleRetentionPolicy" + }, + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunDays": [ + "Monday" + ], + "scheduleRunFrequency": "Weekly", + "scheduleRunTimes": [ + "2017-03-07T02:00:00Z" + ], + "scheduleWeeklyFrequency": 0 + } + }, + { + "policyType": "Log", + "retentionPolicy": { + "retentionDuration": { + "count": 15, + "durationType": "Days" + }, + "retentionPolicyType": "SimpleRetentionPolicy" + }, + "schedulePolicy": { + "scheduleFrequencyInMins": 120, + "schedulePolicyType": "LogSchedulePolicy" + } + } + ], + "workLoadType": "SQLDataBase" + } + }, + { + "name": "filesharepolicy", + "properties": { + "backupManagementType": "AzureStorage", + "protectedItemsCount": 0, + "retentionPolicy": { + "dailySchedule": { + "retentionDuration": { + "count": 30, + "durationType": "Days" + }, + "retentionTimes": [ + "2019-11-07T04:30:00Z" + ] + }, + "retentionPolicyType": "LongTermRetentionPolicy" + }, + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunFrequency": "Daily", + "scheduleRunTimes": [ + "2019-11-07T04:30:00Z" + ], + "scheduleWeeklyFrequency": 0 + }, + "timeZone": "UTC", + "workloadType": "AzureFileShare" + } + } + ] + }, + "backupStorageConfig": { + "value": { + "crossRegionRestoreFlag": true, + "storageModelType": "GeoRedundant" + } + }, + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "enableTelemetry": { + "value": "" + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "managedIdentities": { + "value": { + "systemAssigned": true, + "userAssignedResourceIds": [ + "" + ] + } + }, + "monitoringSettings": { + "value": { + "azureMonitorAlertSettings": { + "alertsForAllJobFailures": "Enabled" + }, + "classicAlertSettings": { + "alertsForCriticalOperations": "Enabled" + } + } + }, + "privateEndpoints": { + "value": [ + { + "ipConfigurations": [ + { + "name": "myIpConfig-1", + "properties": { + "groupId": "AzureSiteRecovery", + "memberName": "SiteRecovery-tel1", + "privateIPAddress": "10.0.0.10" + } + }, + { + "name": "myIPconfig-2", + "properties": { + "groupId": "AzureSiteRecovery", + "memberName": "SiteRecovery-prot2", + "privateIPAddress": "10.0.0.11" + } + }, + { + "name": "myIPconfig-3", + "properties": { + "groupId": "AzureSiteRecovery", + "memberName": "SiteRecovery-srs1", + "privateIPAddress": "10.0.0.12" + } + }, + { + "name": "myIPconfig-4", + "properties": { + "groupId": "AzureSiteRecovery", + "memberName": "SiteRecovery-rcm1", + "privateIPAddress": "10.0.0.13" + } + }, + { + "name": "myIPconfig-5", + "properties": { + "groupId": "AzureSiteRecovery", + "memberName": "SiteRecovery-id1", + "privateIPAddress": "10.0.0.14" + } + } + ], + "privateDnsZoneResourceIds": [ + "" + ], + "subnetResourceId": "", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + ] + }, + "replicationAlertSettings": { + "value": { + "customEmailAddresses": [ + "test.user@testcompany.com" + ], + "locale": "en-US", + "sendToOwners": "Send" + } + }, + "securitySettings": { + "value": { + "immutabilitySettings": { + "state": "Unlocked" + } + } + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

+ + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the Azure Recovery Service Vault. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`backupConfig`](#parameter-backupconfig) | object | The backup configuration. | +| [`backupPolicies`](#parameter-backuppolicies) | array | List of all backup policies. | +| [`backupStorageConfig`](#parameter-backupstorageconfig) | object | The storage configuration for the Azure Recovery Service Vault. | +| [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | +| [`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. | +| [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. | +| [`monitoringSettings`](#parameter-monitoringsettings) | object | Monitoring Settings of the vault. | +| [`privateEndpoints`](#parameter-privateendpoints) | array | Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible. | +| [`protectionContainers`](#parameter-protectioncontainers) | array | List of all protection containers. | +| [`publicNetworkAccess`](#parameter-publicnetworkaccess) | string | Whether or not public network access is allowed for this resource. For security reasons it should be disabled. | +| [`replicationAlertSettings`](#parameter-replicationalertsettings) | object | Replication alert settings. | +| [`replicationFabrics`](#parameter-replicationfabrics) | array | List of all replication fabrics. | +| [`replicationPolicies`](#parameter-replicationpolicies) | array | List of all replication policies. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`securitySettings`](#parameter-securitysettings) | object | Security Settings of the vault. | +| [`tags`](#parameter-tags) | object | Tags of the Recovery Service Vault resource. | + +### Parameter: `name` + +Name of the Azure Recovery Service Vault. + +- Required: Yes +- Type: string + +### Parameter: `backupConfig` + +The backup configuration. + +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `backupPolicies` + +List of all backup policies. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `backupStorageConfig` + +The storage configuration for the Azure Recovery Service Vault. + +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `diagnosticSettings` + +The diagnostic settings of the service. + +- Required: No +- Type: array + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`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 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. | +| [`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. | + +### Parameter: `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: `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: `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: `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. + +- Required: No +- Type: string + +### Parameter: `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-diagnosticsettingsmetriccategoriescategory) | 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-diagnosticsettingsmetriccategoriesenabled) | bool | Enable or disable the category explicitly. Default is `true`. | + +### Parameter: `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: `diagnosticSettings.metricCategories.enabled` + +Enable or disable the category explicitly. Default is `true`. + +- Required: No +- Type: bool + +### Parameter: `diagnosticSettings.name` + +The name of diagnostic setting. + +- Required: No +- Type: string + +### Parameter: `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: `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: `enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `location` + +Location for all resources. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### 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. + +- 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. | + +### 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: No +- Type: array + +### Parameter: `monitoringSettings` + +Monitoring Settings of the vault. + +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `privateEndpoints` + +Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`subnetResourceId`](#parameter-privateendpointssubnetresourceid) | string | Resource ID of the subnet where the endpoint needs to be created. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`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. | +| [`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. | +| [`isManualConnection`](#parameter-privateendpointsismanualconnection) | bool | If Manual Private Link Connection is required. | +| [`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. | +| [`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. | + +### Parameter: `privateEndpoints.subnetResourceId` + +Resource ID of the subnet where the endpoint needs to be created. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.applicationSecurityGroupResourceIds` + +Application security groups in which the private endpoint IP configuration is included. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.customDnsConfigs` + +Custom DNS configurations. + +- Required: No +- Type: array + +**Required parameters** + +| 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. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` + +A list of private IP addresses of the private endpoint. + +- Required: Yes +- Type: array + +### Parameter: `privateEndpoints.customNetworkInterfaceName` + +The custom name of the network interface attached to the private endpoint. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool + +### Parameter: `privateEndpoints.ipConfigurations` + +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 + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-privateendpointsipconfigurationsname) | string | The name of the resource that is unique within a resource group. | +| [`properties`](#parameter-privateendpointsipconfigurationsproperties) | object | Properties of private endpoint IP configurations. | + +### Parameter: `privateEndpoints.ipConfigurations.name` + +The name of the resource that is unique within a resource group. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.ipConfigurations.properties` + +Properties of private endpoint IP configurations. + +- Required: Yes +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`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. | + +### Parameter: `privateEndpoints.ipConfigurations.properties.groupId` + +The ID of a group obtained from the remote resource that this private endpoint should connect to. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.ipConfigurations.properties.memberName` + +The member name of a group obtained from the remote resource that this private endpoint should connect to. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.ipConfigurations.properties.privateIPAddress` + +A private IP address obtained from the private endpoint's subnet. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.isManualConnection` + +If Manual Private Link Connection is required. + +- Required: No +- Type: bool + +### Parameter: `privateEndpoints.location` + +The location to deploy the private endpoint to. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.lock` + +Specify the type of lock. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`kind`](#parameter-privateendpointslockkind) | string | Specify the type of lock. | +| [`name`](#parameter-privateendpointslockname) | string | Specify the name of lock. | + +### Parameter: `privateEndpoints.lock.kind` + +Specify the type of lock. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'CanNotDelete' + 'None' + 'ReadOnly' + ] + ``` + +### Parameter: `privateEndpoints.lock.name` + +Specify the name of lock. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.manualConnectionRequestMessage` + +A message passed to the owner of the remote resource with the manual connection request. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.name` + +The name of the private endpoint. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.privateDnsZoneGroupName` + +The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.privateDnsZoneResourceIds` + +The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`principalId`](#parameter-privateendpointsroleassignmentsprincipalid) | string | The principal ID of the principal (user/group/identity) to assign the role to. | +| [`roleDefinitionIdOrName`](#parameter-privateendpointsroleassignmentsroledefinitionidorname) | 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-privateendpointsroleassignmentscondition) | 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-privateendpointsroleassignmentsconditionversion) | string | Version of the condition. | +| [`delegatedManagedIdentityResourceId`](#parameter-privateendpointsroleassignmentsdelegatedmanagedidentityresourceid) | string | The Resource Id of the delegated managed identity resource. | +| [`description`](#parameter-privateendpointsroleassignmentsdescription) | string | The description of the role assignment. | +| [`principalType`](#parameter-privateendpointsroleassignmentsprincipaltype) | string | The principal type of the assigned principal ID. | + +### Parameter: `privateEndpoints.roleAssignments.principalId` + +The principal ID of the principal (user/group/identity) to assign the role to. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.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: `privateEndpoints.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: `privateEndpoints.roleAssignments.conditionVersion` + +Version of the condition. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + '2.0' + ] + ``` + +### Parameter: `privateEndpoints.roleAssignments.delegatedManagedIdentityResourceId` + +The Resource Id of the delegated managed identity resource. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.roleAssignments.description` + +The description of the role assignment. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.roleAssignments.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `privateEndpoints.service` + +The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.tags` + +Tags to be applied on all resources/resource groups in this deployment. + +- Required: No +- Type: object + +### Parameter: `protectionContainers` + +List of all protection containers. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `publicNetworkAccess` + +Whether or not public network access is allowed for this resource. For security reasons it should be disabled. + +- Required: No +- Type: string +- Default: `'Disabled'` +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `replicationAlertSettings` + +Replication alert settings. + +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `replicationFabrics` + +List of all replication fabrics. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `replicationPolicies` + +List of all replication policies. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**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. | +| [`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.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `securitySettings` + +Security Settings of the vault. + +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `tags` + +Tags of the Recovery Service Vault resource. + +- Required: No +- Type: object + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The Name of the recovery services vault. | +| `resourceGroupName` | string | The name of the resource group the recovery services vault was created in. | +| `resourceId` | string | The resource ID of the recovery services vault. | +| `systemAssignedMIPrincipalId` | string | The principal ID of the system assigned identity. | + +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other CARML 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/network/private-endpoint:0.4.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/recovery-services/vault/backup-config/README.md b/avm/res/recovery-services/vault/backup-config/README.md new file mode 100644 index 0000000000..027a53c4bd --- /dev/null +++ b/avm/res/recovery-services/vault/backup-config/README.md @@ -0,0 +1,165 @@ +# Recovery Services Vault Backup Config `[Microsoft.RecoveryServices/vaults/backupconfig]` + +This module deploys a Recovery Services Vault Backup Config. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.RecoveryServices/vaults/backupconfig` | [2023-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2023-01-01/vaults/backupconfig) | + +## Parameters + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`recoveryVaultName`](#parameter-recoveryvaultname) | string | The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`enhancedSecurityState`](#parameter-enhancedsecuritystate) | string | Enable this setting to protect hybrid backups against accidental deletes and add additional layer of authentication for critical operations. | +| [`isSoftDeleteFeatureStateEditable`](#parameter-issoftdeletefeaturestateeditable) | bool | Is soft delete feature state editable. | +| [`name`](#parameter-name) | string | Name of the Azure Recovery Service Vault Backup Policy. | +| [`resourceGuardOperationRequests`](#parameter-resourceguardoperationrequests) | array | ResourceGuard Operation Requests. | +| [`softDeleteFeatureState`](#parameter-softdeletefeaturestate) | string | Enable this setting to protect backup data for Azure VM, SQL Server in Azure VM and SAP HANA in Azure VM from accidental deletes. | +| [`storageModelType`](#parameter-storagemodeltype) | string | Storage type. | +| [`storageType`](#parameter-storagetype) | string | Storage type. | +| [`storageTypeState`](#parameter-storagetypestate) | string | Once a machine is registered against a resource, the storageTypeState is always Locked. | + +### Parameter: `recoveryVaultName` + +The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `enhancedSecurityState` + +Enable this setting to protect hybrid backups against accidental deletes and add additional layer of authentication for critical operations. + +- Required: No +- Type: string +- Default: `'Enabled'` +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `isSoftDeleteFeatureStateEditable` + +Is soft delete feature state editable. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `name` + +Name of the Azure Recovery Service Vault Backup Policy. + +- Required: No +- Type: string +- Default: `'vaultconfig'` + +### Parameter: `resourceGuardOperationRequests` + +ResourceGuard Operation Requests. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `softDeleteFeatureState` + +Enable this setting to protect backup data for Azure VM, SQL Server in Azure VM and SAP HANA in Azure VM from accidental deletes. + +- Required: No +- Type: string +- Default: `'Enabled'` +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `storageModelType` + +Storage type. + +- Required: No +- Type: string +- Default: `'GeoRedundant'` +- Allowed: + ```Bicep + [ + 'GeoRedundant' + 'LocallyRedundant' + 'ReadAccessGeoZoneRedundant' + 'ZoneRedundant' + ] + ``` + +### Parameter: `storageType` + +Storage type. + +- Required: No +- Type: string +- Default: `'GeoRedundant'` +- Allowed: + ```Bicep + [ + 'GeoRedundant' + 'LocallyRedundant' + 'ReadAccessGeoZoneRedundant' + 'ZoneRedundant' + ] + ``` + +### Parameter: `storageTypeState` + +Once a machine is registered against a resource, the storageTypeState is always Locked. + +- Required: No +- Type: string +- Default: `'Locked'` +- Allowed: + ```Bicep + [ + 'Locked' + 'Unlocked' + ] + ``` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the backup config. | +| `resourceGroupName` | string | The name of the resource group the backup config was created in. | +| `resourceId` | string | The resource ID of the backup config. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/recovery-services/vault/backup-config/main.bicep b/avm/res/recovery-services/vault/backup-config/main.bicep new file mode 100644 index 0000000000..d2d68e9488 --- /dev/null +++ b/avm/res/recovery-services/vault/backup-config/main.bicep @@ -0,0 +1,81 @@ +metadata name = 'Recovery Services Vault Backup Config' +metadata description = 'This module deploys a Recovery Services Vault Backup Config.' +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('Optional. Name of the Azure Recovery Service Vault Backup Policy.') +param name string = 'vaultconfig' + +@description('Optional. Enable this setting to protect hybrid backups against accidental deletes and add additional layer of authentication for critical operations.') +@allowed([ + 'Disabled' + 'Enabled' +]) +param enhancedSecurityState string = 'Enabled' + +@description('Optional. ResourceGuard Operation Requests.') +param resourceGuardOperationRequests array = [] + +@description('Optional. Enable this setting to protect backup data for Azure VM, SQL Server in Azure VM and SAP HANA in Azure VM from accidental deletes.') +@allowed([ + 'Disabled' + 'Enabled' +]) +param softDeleteFeatureState string = 'Enabled' + +@description('Optional. Storage type.') +@allowed([ + 'GeoRedundant' + 'LocallyRedundant' + 'ReadAccessGeoZoneRedundant' + 'ZoneRedundant' +]) +param storageModelType string = 'GeoRedundant' + +@description('Optional. Storage type.') +@allowed([ + 'GeoRedundant' + 'LocallyRedundant' + 'ReadAccessGeoZoneRedundant' + 'ZoneRedundant' +]) +param storageType string = 'GeoRedundant' + +@description('Optional. Once a machine is registered against a resource, the storageTypeState is always Locked.') +@allowed([ + 'Locked' + 'Unlocked' +]) +param storageTypeState string = 'Locked' + +@description('Optional. Is soft delete feature state editable.') +param isSoftDeleteFeatureStateEditable bool = true + +resource rsv 'Microsoft.RecoveryServices/vaults@2023-01-01' existing = { + name: recoveryVaultName +} + +resource backupConfig 'Microsoft.RecoveryServices/vaults/backupconfig@2023-01-01' = { + name: name + parent: rsv + properties: { + enhancedSecurityState: enhancedSecurityState + resourceGuardOperationRequests: resourceGuardOperationRequests + softDeleteFeatureState: softDeleteFeatureState + storageModelType: storageModelType + storageType: storageType + storageTypeState: storageTypeState + isSoftDeleteFeatureStateEditable: isSoftDeleteFeatureStateEditable + } +} + +@description('The name of the backup config.') +output name string = backupConfig.name + +@description('The resource ID of the backup config.') +output resourceId string = backupConfig.id + +@description('The name of the resource group the backup config was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/avm/res/recovery-services/vault/backup-config/main.json b/avm/res/recovery-services/vault/backup-config/main.json new file mode 100644 index 0000000000..e8f0e8c0a5 --- /dev/null +++ b/avm/res/recovery-services/vault/backup-config/main.json @@ -0,0 +1,141 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "15423985878725052790" + }, + "name": "Recovery Services Vault Backup Config", + "description": "This module deploys a Recovery Services Vault Backup Config.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "defaultValue": "vaultconfig", + "metadata": { + "description": "Optional. Name of the Azure Recovery Service Vault Backup Policy." + } + }, + "enhancedSecurityState": { + "type": "string", + "defaultValue": "Enabled", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "metadata": { + "description": "Optional. Enable this setting to protect hybrid backups against accidental deletes and add additional layer of authentication for critical operations." + } + }, + "resourceGuardOperationRequests": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. ResourceGuard Operation Requests." + } + }, + "softDeleteFeatureState": { + "type": "string", + "defaultValue": "Enabled", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "metadata": { + "description": "Optional. Enable this setting to protect backup data for Azure VM, SQL Server in Azure VM and SAP HANA in Azure VM from accidental deletes." + } + }, + "storageModelType": { + "type": "string", + "defaultValue": "GeoRedundant", + "allowedValues": [ + "GeoRedundant", + "LocallyRedundant", + "ReadAccessGeoZoneRedundant", + "ZoneRedundant" + ], + "metadata": { + "description": "Optional. Storage type." + } + }, + "storageType": { + "type": "string", + "defaultValue": "GeoRedundant", + "allowedValues": [ + "GeoRedundant", + "LocallyRedundant", + "ReadAccessGeoZoneRedundant", + "ZoneRedundant" + ], + "metadata": { + "description": "Optional. Storage type." + } + }, + "storageTypeState": { + "type": "string", + "defaultValue": "Locked", + "allowedValues": [ + "Locked", + "Unlocked" + ], + "metadata": { + "description": "Optional. Once a machine is registered against a resource, the storageTypeState is always Locked." + } + }, + "isSoftDeleteFeatureStateEditable": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Is soft delete feature state editable." + } + } + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/backupconfig", + "apiVersion": "2023-01-01", + "name": "[format('{0}/{1}', parameters('recoveryVaultName'), parameters('name'))]", + "properties": { + "enhancedSecurityState": "[parameters('enhancedSecurityState')]", + "resourceGuardOperationRequests": "[parameters('resourceGuardOperationRequests')]", + "softDeleteFeatureState": "[parameters('softDeleteFeatureState')]", + "storageModelType": "[parameters('storageModelType')]", + "storageType": "[parameters('storageType')]", + "storageTypeState": "[parameters('storageTypeState')]", + "isSoftDeleteFeatureStateEditable": "[parameters('isSoftDeleteFeatureStateEditable')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the backup config." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the backup config." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/backupconfig', parameters('recoveryVaultName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the backup config was created in." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/recovery-services/vault/backup-fabric/protection-container/README.md b/avm/res/recovery-services/vault/backup-fabric/protection-container/README.md new file mode 100644 index 0000000000..b0ea336ddd --- /dev/null +++ b/avm/res/recovery-services/vault/backup-fabric/protection-container/README.md @@ -0,0 +1,146 @@ +# Recovery Services Vault Protection Container `[Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers]` + +This module deploys a Recovery Services Vault Protection Container. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers` | [2023-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2023-01-01/vaults/backupFabrics/protectionContainers) | +| `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) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the Azure Recovery Service Vault Protection Container. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`recoveryVaultName`](#parameter-recoveryvaultname) | string | The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`backupManagementType`](#parameter-backupmanagementtype) | string | Backup management type to execute the current Protection Container job. | +| [`containerType`](#parameter-containertype) | string | Type of the container. | +| [`friendlyName`](#parameter-friendlyname) | string | Friendly name of the Protection Container. | +| [`location`](#parameter-location) | string | Location for all resources. | +| [`protectedItems`](#parameter-protecteditems) | array | Protected items to register in the container. | +| [`sourceResourceId`](#parameter-sourceresourceid) | string | Resource ID of the target resource for the Protection Container. | + +### Parameter: `name` + +Name of the Azure Recovery Service Vault Protection Container. + +- Required: Yes +- Type: string + +### Parameter: `recoveryVaultName` + +The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `backupManagementType` + +Backup management type to execute the current Protection Container job. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'AzureBackupServer' + 'AzureIaasVM' + 'AzureSql' + 'AzureStorage' + 'AzureWorkload' + 'DefaultBackup' + 'DPM' + 'Invalid' + 'MAB' + ] + ``` + +### Parameter: `containerType` + +Type of the container. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'AzureBackupServerContainer' + 'AzureSqlContainer' + 'GenericContainer' + 'Microsoft.ClassicCompute/virtualMachines' + 'Microsoft.Compute/virtualMachines' + 'SQLAGWorkLoadContainer' + 'StorageContainer' + 'VMAppContainer' + 'Windows' + ] + ``` + +### Parameter: `friendlyName` + +Friendly name of the Protection Container. + +- Required: No +- Type: string + +### Parameter: `location` + +Location for all resources. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `protectedItems` + +Protected items to register in the container. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `sourceResourceId` + +Resource ID of the target resource for the Protection Container. + +- Required: No +- Type: string + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The Name of the Protection Container. | +| `resourceGroupName` | string | The name of the Resource Group the Protection Container was created in. | +| `resourceId` | string | The resource ID of the Protection Container. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/recovery-services/vault/backup-fabric/protection-container/main.bicep b/avm/res/recovery-services/vault/backup-fabric/protection-container/main.bicep new file mode 100644 index 0000000000..693126a32f --- /dev/null +++ b/avm/res/recovery-services/vault/backup-fabric/protection-container/main.bicep @@ -0,0 +1,81 @@ +metadata name = 'Recovery Services Vault Protection Container' +metadata description = 'This module deploys a Recovery Services Vault Protection Container.' +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. Name of the Azure Recovery Service Vault Protection Container.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Backup management type to execute the current Protection Container job.') +@allowed([ + 'AzureBackupServer' + 'AzureIaasVM' + 'AzureSql' + 'AzureStorage' + 'AzureWorkload' + 'DPM' + 'DefaultBackup' + 'Invalid' + 'MAB' +]) +param backupManagementType string? + +@description('Optional. Resource ID of the target resource for the Protection Container.') +param sourceResourceId string? + +@description('Optional. Friendly name of the Protection Container.') +param friendlyName string? + +@description('Optional. Protected items to register in the container.') +param protectedItems array = [] + +@description('Optional. Type of the container.') +@allowed([ + 'AzureBackupServerContainer' + 'AzureSqlContainer' + 'GenericContainer' + 'Microsoft.ClassicCompute/virtualMachines' + 'Microsoft.Compute/virtualMachines' + 'SQLAGWorkLoadContainer' + 'StorageContainer' + 'VMAppContainer' + 'Windows' +]) +param containerType string? + +resource protectionContainer 'Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers@2023-01-01' = { + name: '${recoveryVaultName}/Azure/${name}' + properties: { + sourceResourceId: sourceResourceId + friendlyName: friendlyName + backupManagementType: backupManagementType + containerType: !empty(containerType) ? any(containerType) : null + } +} + +module protectionContainer_protectedItems 'protected-item/main.bicep' = [for (protectedItem, index) in protectedItems: { + name: '${uniqueString(deployment().name, location)}-ProtectedItem-${index}' + params: { + policyId: protectedItem.policyId + name: protectedItem.name + protectedItemType: protectedItem.protectedItemType + protectionContainerName: protectionContainer.name + recoveryVaultName: recoveryVaultName + sourceResourceId: protectedItem.sourceResourceId + location: location + } +}] + +@description('The name of the Resource Group the Protection Container was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the Protection Container.') +output resourceId string = protectionContainer.id + +@description('The Name of the Protection Container.') +output name string = protectionContainer.name diff --git a/avm/res/recovery-services/vault/backup-fabric/protection-container/main.json b/avm/res/recovery-services/vault/backup-fabric/protection-container/main.json new file mode 100644 index 0000000000..9a0b367fcc --- /dev/null +++ b/avm/res/recovery-services/vault/backup-fabric/protection-container/main.json @@ -0,0 +1,277 @@ +{ + "$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": "5887508216739936022" + }, + "name": "Recovery Services Vault Protection Container", + "description": "This module deploys a Recovery Services Vault Protection Container.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Azure Recovery Service Vault Protection Container." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "backupManagementType": { + "type": "string", + "nullable": true, + "allowedValues": [ + "AzureBackupServer", + "AzureIaasVM", + "AzureSql", + "AzureStorage", + "AzureWorkload", + "DPM", + "DefaultBackup", + "Invalid", + "MAB" + ], + "metadata": { + "description": "Optional. Backup management type to execute the current Protection Container job." + } + }, + "sourceResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the target resource for the Protection Container." + } + }, + "friendlyName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Friendly name of the Protection Container." + } + }, + "protectedItems": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Protected items to register in the container." + } + }, + "containerType": { + "type": "string", + "nullable": true, + "allowedValues": [ + "AzureBackupServerContainer", + "AzureSqlContainer", + "GenericContainer", + "Microsoft.ClassicCompute/virtualMachines", + "Microsoft.Compute/virtualMachines", + "SQLAGWorkLoadContainer", + "StorageContainer", + "VMAppContainer", + "Windows" + ], + "metadata": { + "description": "Optional. Type of the container." + } + } + }, + "resources": { + "protectionContainer": { + "type": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers", + "apiVersion": "2023-01-01", + "name": "[format('{0}/Azure/{1}', parameters('recoveryVaultName'), parameters('name'))]", + "properties": { + "sourceResourceId": "[parameters('sourceResourceId')]", + "friendlyName": "[parameters('friendlyName')]", + "backupManagementType": "[parameters('backupManagementType')]", + "containerType": "[if(not(empty(parameters('containerType'))), parameters('containerType'), null())]" + } + }, + "protectionContainer_protectedItems": { + "copy": { + "name": "protectionContainer_protectedItems", + "count": "[length(parameters('protectedItems'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-ProtectedItem-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "policyId": { + "value": "[parameters('protectedItems')[copyIndex()].policyId]" + }, + "name": { + "value": "[parameters('protectedItems')[copyIndex()].name]" + }, + "protectedItemType": { + "value": "[parameters('protectedItems')[copyIndex()].protectedItemType]" + }, + "protectionContainerName": { + "value": "[format('{0}/Azure/{1}', parameters('recoveryVaultName'), parameters('name'))]" + }, + "recoveryVaultName": { + "value": "[parameters('recoveryVaultName')]" + }, + "sourceResourceId": { + "value": "[parameters('protectedItems')[copyIndex()].sourceResourceId]" + }, + "location": { + "value": "[parameters('location')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "15677187951825533891" + }, + "name": "Recovery Service Vaults Protection Container Protected Item", + "description": "This module deploys a Recovery Services Vault Protection Container Protected Item.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the resource." + } + }, + "protectionContainerName": { + "type": "string", + "metadata": { + "description": "Conditional. Name of the Azure Recovery Service Vault Protection Container. Required if the template is used in a standalone deployment." + } + }, + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "protectedItemType": { + "type": "string", + "allowedValues": [ + "AzureFileShareProtectedItem", + "AzureVmWorkloadSAPAseDatabase", + "AzureVmWorkloadSAPHanaDatabase", + "AzureVmWorkloadSQLDatabase", + "DPMProtectedItem", + "GenericProtectedItem", + "MabFileFolderProtectedItem", + "Microsoft.ClassicCompute/virtualMachines", + "Microsoft.Compute/virtualMachines", + "Microsoft.Sql/servers/databases" + ], + "metadata": { + "description": "Required. The backup item type." + } + }, + "policyId": { + "type": "string", + "metadata": { + "description": "Required. ID of the backup policy with which this item is backed up." + } + }, + "sourceResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the resource to back up." + } + } + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems", + "apiVersion": "2023-01-01", + "name": "[format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "protectedItemType": "[parameters('protectedItemType')]", + "policyId": "[parameters('policyId')]", + "sourceResourceId": "[parameters('sourceResourceId')]" + } + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the protected item was created in." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the protected item." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems', split(format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name')), '/')[0], split(format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name')), '/')[1], split(format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name')), '/')[2], split(format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name')), '/')[3])]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The Name of the protected item." + }, + "value": "[format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name'))]" + } + } + } + }, + "dependsOn": [ + "protectionContainer" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the Protection Container was created in." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Protection Container." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers', split(format('{0}/Azure/{1}', parameters('recoveryVaultName'), parameters('name')), '/')[0], split(format('{0}/Azure/{1}', parameters('recoveryVaultName'), parameters('name')), '/')[1], split(format('{0}/Azure/{1}', parameters('recoveryVaultName'), parameters('name')), '/')[2])]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The Name of the Protection Container." + }, + "value": "[format('{0}/Azure/{1}', parameters('recoveryVaultName'), parameters('name'))]" + } + } +} \ No newline at end of file diff --git a/avm/res/recovery-services/vault/backup-fabric/protection-container/protected-item/README.md b/avm/res/recovery-services/vault/backup-fabric/protection-container/protected-item/README.md new file mode 100644 index 0000000000..87299f4c76 --- /dev/null +++ b/avm/res/recovery-services/vault/backup-fabric/protection-container/protected-item/README.md @@ -0,0 +1,123 @@ +# Recovery Service Vaults Protection Container Protected Item `[Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems]` + +This module deploys a Recovery Services Vault Protection Container Protected Item. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `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) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the resource. | +| [`policyId`](#parameter-policyid) | string | ID of the backup policy with which this item is backed up. | +| [`protectedItemType`](#parameter-protecteditemtype) | string | The backup item type. | +| [`sourceResourceId`](#parameter-sourceresourceid) | string | Resource ID of the resource to back up. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`protectionContainerName`](#parameter-protectioncontainername) | string | Name of the Azure Recovery Service Vault Protection Container. Required if the template is used in a standalone deployment. | +| [`recoveryVaultName`](#parameter-recoveryvaultname) | string | The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`location`](#parameter-location) | string | Location for all resources. | + +### Parameter: `name` + +Name of the resource. + +- Required: Yes +- Type: string + +### Parameter: `policyId` + +ID of the backup policy with which this item is backed up. + +- Required: Yes +- Type: string + +### Parameter: `protectedItemType` + +The backup item type. + +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'AzureFileShareProtectedItem' + 'AzureVmWorkloadSAPAseDatabase' + 'AzureVmWorkloadSAPHanaDatabase' + 'AzureVmWorkloadSQLDatabase' + 'DPMProtectedItem' + 'GenericProtectedItem' + 'MabFileFolderProtectedItem' + 'Microsoft.ClassicCompute/virtualMachines' + 'Microsoft.Compute/virtualMachines' + 'Microsoft.Sql/servers/databases' + ] + ``` + +### Parameter: `sourceResourceId` + +Resource ID of the resource to back up. + +- Required: Yes +- Type: string + +### Parameter: `protectionContainerName` + +Name of the Azure Recovery Service Vault Protection Container. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `recoveryVaultName` + +The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `location` + +Location for all resources. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The Name of the protected item. | +| `resourceGroupName` | string | The name of the Resource Group the protected item was created in. | +| `resourceId` | string | The resource ID of the protected item. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/recovery-services/vault/backup-fabric/protection-container/protected-item/main.bicep b/avm/res/recovery-services/vault/backup-fabric/protection-container/protected-item/main.bicep new file mode 100644 index 0000000000..dbba0616ac --- /dev/null +++ b/avm/res/recovery-services/vault/backup-fabric/protection-container/protected-item/main.bicep @@ -0,0 +1,55 @@ +metadata name = 'Recovery Service Vaults Protection Container Protected Item' +metadata description = 'This module deploys a Recovery Services Vault Protection Container Protected Item.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. Name of the resource.') +param name string + +@description('Conditional. Name of the Azure Recovery Service Vault Protection Container. Required if the template is used in a standalone deployment.') +param protectionContainerName string + +@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('Optional. Location for all resources.') +param location string = resourceGroup().location + +@allowed([ + 'AzureFileShareProtectedItem' + 'AzureVmWorkloadSAPAseDatabase' + 'AzureVmWorkloadSAPHanaDatabase' + 'AzureVmWorkloadSQLDatabase' + 'DPMProtectedItem' + 'GenericProtectedItem' + 'MabFileFolderProtectedItem' + 'Microsoft.ClassicCompute/virtualMachines' + 'Microsoft.Compute/virtualMachines' + 'Microsoft.Sql/servers/databases' +]) +@description('Required. The backup item type.') +param protectedItemType string + +@description('Required. ID of the backup policy with which this item is backed up.') +param policyId string + +@description('Required. Resource ID of the resource to back up.') +param sourceResourceId string + +resource protectedItem 'Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems@2023-01-01' = { + name: '${recoveryVaultName}/Azure/${protectionContainerName}/${name}' + location: location + properties: { + protectedItemType: any(protectedItemType) + policyId: policyId + sourceResourceId: sourceResourceId + } +} + +@description('The name of the Resource Group the protected item was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the protected item.') +output resourceId string = protectedItem.id + +@description('The Name of the protected item.') +output name string = protectedItem.name 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 new file mode 100644 index 0000000000..880a35cef4 --- /dev/null +++ b/avm/res/recovery-services/vault/backup-fabric/protection-container/protected-item/main.json @@ -0,0 +1,107 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "15677187951825533891" + }, + "name": "Recovery Service Vaults Protection Container Protected Item", + "description": "This module deploys a Recovery Services Vault Protection Container Protected Item.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the resource." + } + }, + "protectionContainerName": { + "type": "string", + "metadata": { + "description": "Conditional. Name of the Azure Recovery Service Vault Protection Container. Required if the template is used in a standalone deployment." + } + }, + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "protectedItemType": { + "type": "string", + "allowedValues": [ + "AzureFileShareProtectedItem", + "AzureVmWorkloadSAPAseDatabase", + "AzureVmWorkloadSAPHanaDatabase", + "AzureVmWorkloadSQLDatabase", + "DPMProtectedItem", + "GenericProtectedItem", + "MabFileFolderProtectedItem", + "Microsoft.ClassicCompute/virtualMachines", + "Microsoft.Compute/virtualMachines", + "Microsoft.Sql/servers/databases" + ], + "metadata": { + "description": "Required. The backup item type." + } + }, + "policyId": { + "type": "string", + "metadata": { + "description": "Required. ID of the backup policy with which this item is backed up." + } + }, + "sourceResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the resource to back up." + } + } + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems", + "apiVersion": "2023-01-01", + "name": "[format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "protectedItemType": "[parameters('protectedItemType')]", + "policyId": "[parameters('policyId')]", + "sourceResourceId": "[parameters('sourceResourceId')]" + } + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the protected item was created in." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the protected item." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems', split(format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name')), '/')[0], split(format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name')), '/')[1], split(format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name')), '/')[2], split(format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name')), '/')[3])]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The Name of the protected item." + }, + "value": "[format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name'))]" + } + } +} \ No newline at end of file diff --git a/avm/res/recovery-services/vault/backup-policy/README.md b/avm/res/recovery-services/vault/backup-policy/README.md new file mode 100644 index 0000000000..5d982301c3 --- /dev/null +++ b/avm/res/recovery-services/vault/backup-policy/README.md @@ -0,0 +1,70 @@ +# Recovery Services Vault Backup Policies `[Microsoft.RecoveryServices/vaults/backupPolicies]` + +This module deploys a Recovery Services Vault Backup Policy. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.RecoveryServices/vaults/backupPolicies` | [2023-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2023-01-01/vaults/backupPolicies) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the Azure Recovery Service Vault Backup Policy. | +| [`properties`](#parameter-properties) | object | Configuration of the Azure Recovery Service Vault Backup Policy. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`recoveryVaultName`](#parameter-recoveryvaultname) | string | The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment. | + +### Parameter: `name` + +Name of the Azure Recovery Service Vault Backup Policy. + +- Required: Yes +- Type: string + +### Parameter: `properties` + +Configuration of the Azure Recovery Service Vault Backup Policy. + +- Required: Yes +- Type: object + +### Parameter: `recoveryVaultName` + +The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the backup policy. | +| `resourceGroupName` | string | The name of the resource group the backup policy was created in. | +| `resourceId` | string | The resource ID of the backup policy. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/recovery-services/vault/backup-policy/main.bicep b/avm/res/recovery-services/vault/backup-policy/main.bicep new file mode 100644 index 0000000000..4df92f49c2 --- /dev/null +++ b/avm/res/recovery-services/vault/backup-policy/main.bicep @@ -0,0 +1,31 @@ +metadata name = 'Recovery Services Vault Backup Policies' +metadata description = 'This module deploys a Recovery Services Vault Backup Policy.' +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. Name of the Azure Recovery Service Vault Backup Policy.') +param name string + +@description('Required. Configuration of the Azure Recovery Service Vault Backup Policy.') +param properties object + +resource rsv 'Microsoft.RecoveryServices/vaults@2023-01-01' existing = { + name: recoveryVaultName +} + +resource backupPolicy 'Microsoft.RecoveryServices/vaults/backupPolicies@2023-01-01' = { + name: name + parent: rsv + properties: properties +} + +@description('The name of the backup policy.') +output name string = backupPolicy.name + +@description('The resource ID of the backup policy.') +output resourceId string = backupPolicy.id + +@description('The name of the resource group the backup policy was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/avm/res/recovery-services/vault/backup-policy/main.json b/avm/res/recovery-services/vault/backup-policy/main.json new file mode 100644 index 0000000000..53c8a67f66 --- /dev/null +++ b/avm/res/recovery-services/vault/backup-policy/main.json @@ -0,0 +1,65 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "3329904805287164035" + }, + "name": "Recovery Services Vault Backup Policies", + "description": "This module deploys a Recovery Services Vault Backup Policy.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Azure Recovery Service Vault Backup Policy." + } + }, + "properties": { + "type": "object", + "metadata": { + "description": "Required. Configuration of the Azure Recovery Service Vault Backup Policy." + } + } + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/backupPolicies", + "apiVersion": "2023-01-01", + "name": "[format('{0}/{1}', parameters('recoveryVaultName'), parameters('name'))]", + "properties": "[parameters('properties')]" + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the backup policy." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the backup policy." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/backupPolicies', parameters('recoveryVaultName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the backup policy was created in." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/recovery-services/vault/backup-storage-config/README.md b/avm/res/recovery-services/vault/backup-storage-config/README.md new file mode 100644 index 0000000000..d586aa0c7e --- /dev/null +++ b/avm/res/recovery-services/vault/backup-storage-config/README.md @@ -0,0 +1,90 @@ +# Recovery Services Vault Backup Storage Config `[Microsoft.RecoveryServices/vaults/backupstorageconfig]` + +This module deploys a Recovery Service Vault Backup Storage Configuration. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.RecoveryServices/vaults/backupstorageconfig` | [2023-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2023-01-01/vaults/backupstorageconfig) | + +## Parameters + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`recoveryVaultName`](#parameter-recoveryvaultname) | string | The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`crossRegionRestoreFlag`](#parameter-crossregionrestoreflag) | bool | Opt in details of Cross Region Restore feature. | +| [`name`](#parameter-name) | string | The name of the backup storage config. | +| [`storageModelType`](#parameter-storagemodeltype) | string | Change Vault Storage Type (Works if vault has not registered any backup instance). | + +### Parameter: `recoveryVaultName` + +The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `crossRegionRestoreFlag` + +Opt in details of Cross Region Restore feature. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `name` + +The name of the backup storage config. + +- Required: No +- Type: string +- Default: `'vaultstorageconfig'` + +### Parameter: `storageModelType` + +Change Vault Storage Type (Works if vault has not registered any backup instance). + +- Required: No +- Type: string +- Default: `'GeoRedundant'` +- Allowed: + ```Bicep + [ + 'GeoRedundant' + 'LocallyRedundant' + 'ReadAccessGeoZoneRedundant' + 'ZoneRedundant' + ] + ``` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the backup storage config. | +| `resourceGroupName` | string | The name of the Resource Group the backup storage configuration was created in. | +| `resourceId` | string | The resource ID of the backup storage config. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/recovery-services/vault/backup-storage-config/main.bicep b/avm/res/recovery-services/vault/backup-storage-config/main.bicep new file mode 100644 index 0000000000..bb80b18bd7 --- /dev/null +++ b/avm/res/recovery-services/vault/backup-storage-config/main.bicep @@ -0,0 +1,43 @@ +metadata name = 'Recovery Services Vault Backup Storage Config' +metadata description = 'This module deploys a Recovery Service Vault Backup Storage Configuration.' +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('Optional. The name of the backup storage config.') +param name string = 'vaultstorageconfig' + +@description('Optional. Change Vault Storage Type (Works if vault has not registered any backup instance).') +@allowed([ + 'GeoRedundant' + 'LocallyRedundant' + 'ReadAccessGeoZoneRedundant' + 'ZoneRedundant' +]) +param storageModelType string = 'GeoRedundant' + +@description('Optional. Opt in details of Cross Region Restore feature.') +param crossRegionRestoreFlag bool = true + +resource rsv 'Microsoft.RecoveryServices/vaults@2023-01-01' existing = { + name: recoveryVaultName +} + +resource backupStorageConfig 'Microsoft.RecoveryServices/vaults/backupstorageconfig@2023-01-01' = { + name: name + parent: rsv + properties: { + storageModelType: storageModelType + crossRegionRestoreFlag: crossRegionRestoreFlag + } +} + +@description('The name of the backup storage config.') +output name string = backupStorageConfig.name + +@description('The resource ID of the backup storage config.') +output resourceId string = backupStorageConfig.id + +@description('The name of the Resource Group the backup storage configuration was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/avm/res/recovery-services/vault/backup-storage-config/main.json b/avm/res/recovery-services/vault/backup-storage-config/main.json new file mode 100644 index 0000000000..829a4157b1 --- /dev/null +++ b/avm/res/recovery-services/vault/backup-storage-config/main.json @@ -0,0 +1,83 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "16823125725342753814" + }, + "name": "Recovery Services Vault Backup Storage Config", + "description": "This module deploys a Recovery Service Vault Backup Storage Configuration.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "defaultValue": "vaultstorageconfig", + "metadata": { + "description": "Optional. The name of the backup storage config." + } + }, + "storageModelType": { + "type": "string", + "defaultValue": "GeoRedundant", + "allowedValues": [ + "GeoRedundant", + "LocallyRedundant", + "ReadAccessGeoZoneRedundant", + "ZoneRedundant" + ], + "metadata": { + "description": "Optional. Change Vault Storage Type (Works if vault has not registered any backup instance)." + } + }, + "crossRegionRestoreFlag": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Opt in details of Cross Region Restore feature." + } + } + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/backupstorageconfig", + "apiVersion": "2023-01-01", + "name": "[format('{0}/{1}', parameters('recoveryVaultName'), parameters('name'))]", + "properties": { + "storageModelType": "[parameters('storageModelType')]", + "crossRegionRestoreFlag": "[parameters('crossRegionRestoreFlag')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the backup storage config." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the backup storage config." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/backupstorageconfig', parameters('recoveryVaultName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the backup storage configuration was created in." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/recovery-services/vault/main.bicep b/avm/res/recovery-services/vault/main.bicep new file mode 100644 index 0000000000..16126e1d3d --- /dev/null +++ b/avm/res/recovery-services/vault/main.bicep @@ -0,0 +1,453 @@ +metadata name = 'Recovery Services Vaults' +metadata description = 'This module deploys a Recovery Services Vault.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. Name of the Azure Recovery Service Vault.') +param name string + +@description('Optional. The storage configuration for the Azure Recovery Service Vault.') +param backupStorageConfig object = {} + +@description('Optional. Enable/Disable usage telemetry for module.') +param enableTelemetry bool = true + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. List of all backup policies.') +param backupPolicies array = [] + +@description('Optional. The backup configuration.') +param backupConfig object = {} + +@description('Optional. List of all protection containers.') +param protectionContainers array = [] + +@description('Optional. List of all replication fabrics.') +param replicationFabrics array = [] + +@description('Optional. List of all replication policies.') +param replicationPolicies array = [] + +@description('Optional. Replication alert settings.') +param replicationAlertSettings object = {} + +@description('Optional. The diagnostic settings of the service.') +param diagnosticSettings diagnosticSettingType + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +@description('Optional. The lock settings of the service.') +param lock lockType + +@description('Optional. The managed identity definition for this resource.') +param managedIdentities managedIdentitiesType + +@description('Optional. Tags of the Recovery Service Vault resource.') +param tags object? + +@description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') +param privateEndpoints privateEndpointType + +@description('Optional. Monitoring Settings of the vault.') +param monitoringSettings object = {} + +@description('Optional. Security Settings of the vault.') +param securitySettings object = {} + +@description('Optional. Whether or not public network access is allowed for this resource. For security reasons it should be disabled.') +@allowed([ + 'Enabled' + 'Disabled' +]) +param publicNetworkAccess string = 'Disabled' + +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' : 'None') + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null +} : null + +var builtInRoleNames = { + 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') + 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') + 'Backup Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a795c7a0-d4a2-40c1-ae25-d81f01202912') + 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'Site Recovery Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567') + 'Site Recovery Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca') + 'Site Recovery Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dbaa88c4-0c30-4179-9fb3-46319faa6149') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.recoveryservices-vault.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } + } + } + } +} + +resource rsv 'Microsoft.RecoveryServices/vaults@2023-01-01' = { + name: name + location: location + tags: tags + identity: identity + sku: { + name: 'RS0' + tier: 'Standard' + } + properties: { + monitoringSettings: !empty(monitoringSettings) ? monitoringSettings : null + securitySettings: !empty(securitySettings) ? securitySettings : null + publicNetworkAccess: publicNetworkAccess + } +} + +module rsv_replicationFabrics 'replication-fabric/main.bicep' = [for (replicationFabric, index) in replicationFabrics: { + name: '${uniqueString(deployment().name, location)}-RSV-Fabric-${index}' + params: { + recoveryVaultName: rsv.name + name: contains(replicationFabric, 'name') ? replicationFabric.name : replicationFabric.location + location: replicationFabric.location + replicationContainers: contains(replicationFabric, 'replicationContainers') ? replicationFabric.replicationContainers : [] + } + dependsOn: [ + rsv_replicationPolicies + ] +}] + +module rsv_replicationPolicies 'replication-policy/main.bicep' = [for (replicationPolicy, index) in replicationPolicies: { + name: '${uniqueString(deployment().name, location)}-RSV-Policy-${index}' + params: { + name: replicationPolicy.name + recoveryVaultName: rsv.name + appConsistentFrequencyInMinutes: contains(replicationPolicy, 'appConsistentFrequencyInMinutes') ? replicationPolicy.appConsistentFrequencyInMinutes : 60 + crashConsistentFrequencyInMinutes: contains(replicationPolicy, 'crashConsistentFrequencyInMinutes') ? replicationPolicy.crashConsistentFrequencyInMinutes : 5 + multiVmSyncStatus: contains(replicationPolicy, 'multiVmSyncStatus') ? replicationPolicy.multiVmSyncStatus : 'Enable' + recoveryPointHistory: contains(replicationPolicy, 'recoveryPointHistory') ? replicationPolicy.recoveryPointHistory : 1440 + } +}] + +module rsv_backupStorageConfiguration 'backup-storage-config/main.bicep' = if (!empty(backupStorageConfig)) { + name: '${uniqueString(deployment().name, location)}-RSV-BackupStorageConfig' + params: { + recoveryVaultName: rsv.name + storageModelType: backupStorageConfig.storageModelType + crossRegionRestoreFlag: backupStorageConfig.crossRegionRestoreFlag + } +} + +module rsv_backupFabric_protectionContainers 'backup-fabric/protection-container/main.bicep' = [for (protectionContainer, index) in protectionContainers: { + name: '${uniqueString(deployment().name, location)}-RSV-ProtectionContainers-${index}' + params: { + recoveryVaultName: rsv.name + name: protectionContainer.name + sourceResourceId: protectionContainer.?sourceResourceId + friendlyName: protectionContainer.?friendlyName + backupManagementType: protectionContainer.?backupManagementType + containerType: protectionContainer.?containerType + protectedItems: contains(protectionContainer, 'protectedItems') ? protectionContainer.protectedItems : [] + location: location + } +}] + +module rsv_backupPolicies 'backup-policy/main.bicep' = [for (backupPolicy, index) in backupPolicies: { + name: '${uniqueString(deployment().name, location)}-RSV-BackupPolicy-${index}' + params: { + recoveryVaultName: rsv.name + name: backupPolicy.name + properties: backupPolicy.properties + } +}] + +module rsv_backupConfig 'backup-config/main.bicep' = if (!empty(backupConfig)) { + name: '${uniqueString(deployment().name, location)}-RSV-BackupConfig' + params: { + recoveryVaultName: rsv.name + name: contains(backupConfig, 'name') ? backupConfig.name : 'vaultconfig' + enhancedSecurityState: contains(backupConfig, 'enhancedSecurityState') ? backupConfig.enhancedSecurityState : 'Enabled' + resourceGuardOperationRequests: contains(backupConfig, 'resourceGuardOperationRequests') ? backupConfig.resourceGuardOperationRequests : [] + softDeleteFeatureState: contains(backupConfig, 'softDeleteFeatureState') ? backupConfig.softDeleteFeatureState : 'Enabled' + storageModelType: contains(backupConfig, 'storageModelType') ? backupConfig.storageModelType : 'GeoRedundant' + storageType: contains(backupConfig, 'storageType') ? backupConfig.storageType : 'GeoRedundant' + storageTypeState: contains(backupConfig, 'storageTypeState') ? backupConfig.storageTypeState : 'Locked' + isSoftDeleteFeatureStateEditable: contains(backupConfig, 'isSoftDeleteFeatureStateEditable') ? backupConfig.isSoftDeleteFeatureStateEditable : true + } +} + +module rsv_replicationAlertSettings 'replication-alert-setting/main.bicep' = if (!empty(replicationAlertSettings)) { + name: '${uniqueString(deployment().name, location)}-RSV-replicationAlertSettings' + params: { + name: 'defaultAlertSetting' + recoveryVaultName: rsv.name + customEmailAddresses: contains(replicationAlertSettings, 'customEmailAddresses') ? replicationAlertSettings.customEmailAddresses : [] + locale: contains(replicationAlertSettings, 'locale') ? replicationAlertSettings.locale : '' + sendToOwners: contains(replicationAlertSettings, 'sendToOwners') ? replicationAlertSettings.sendToOwners : 'Send' + } +} + +resource rsv_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: rsv +} + +resource rsv_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + }] + logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + }] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: rsv +}] + +module rsv_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-RSV-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(rsv.id, '/'))}-${privateEndpoint.?service ?? 'AzureSiteRecovery'}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(rsv.id, '/'))}-${privateEndpoint.?service ?? 'AzureSiteRecovery'}-${index}' + properties: { + privateLinkServiceId: rsv.id + groupIds: [ + privateEndpoint.?service ?? 'AzureSiteRecovery' + ] + } + } + ] : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(rsv.id, '/'))}-${privateEndpoint.?service ?? 'AzureSiteRecovery'}-${index}' + properties: { + privateLinkServiceId: rsv.id + groupIds: [ + privateEndpoint.?service ?? 'AzureSiteRecovery' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } + ] : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } +}] + +resource rsv_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(rsv.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: rsv +}] + +@description('The resource ID of the recovery services vault.') +output resourceId string = rsv.id + +@description('The name of the resource group the recovery services vault was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The Name of the recovery services vault.') +output name string = rsv.name + +@description('The principal ID of the system assigned identity.') +output systemAssignedMIPrincipalId string = rsv.?identity.?principalId ?? '' + +@description('The location the resource was deployed into.') +output location string = rsv.location + +// =============== // +// 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('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 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? +}[]? + +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/recovery-services/vault/main.json b/avm/res/recovery-services/vault/main.json new file mode 100644 index 0000000000..686a7aa5d3 --- /dev/null +++ b/avm/res/recovery-services/vault/main.json @@ -0,0 +1,2702 @@ +{ + "$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": "916737030536129910" + }, + "name": "Recovery Services Vaults", + "description": "This module deploys a Recovery Services Vault.", + "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": { + "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." + } + }, + "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." + } + } + } + }, + "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 + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Azure Recovery Service Vault." + } + }, + "backupStorageConfig": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The storage configuration for the Azure Recovery Service Vault." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "backupPolicies": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of all backup policies." + } + }, + "backupConfig": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The backup configuration." + } + }, + "protectionContainers": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of all protection containers." + } + }, + "replicationFabrics": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of all replication fabrics." + } + }, + "replicationPolicies": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of all replication policies." + } + }, + "replicationAlertSettings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Replication alert settings." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + }, + "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." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the Recovery Service Vault resource." + } + }, + "privateEndpoints": { + "$ref": "#/definitions/privateEndpointType", + "metadata": { + "description": "Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible." + } + }, + "monitoringSettings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Monitoring Settings of the vault." + } + }, + "securitySettings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Security Settings of the vault." + } + }, + "publicNetworkAccess": { + "type": "string", + "defaultValue": "Disabled", + "allowedValues": [ + "Enabled", + "Disabled" + ], + "metadata": { + "description": "Optional. Whether or not public network access is allowed for this resource. For security reasons it should be disabled." + } + } + }, + "variables": { + "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": { + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "Backup Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a795c7a0-d4a2-40c1-ae25-d81f01202912')]", + "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 (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Site Recovery Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dbaa88c4-0c30-4179-9fb3-46319faa6149')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.recoveryservices-vault.{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" + } + } + } + } + }, + "rsv": { + "type": "Microsoft.RecoveryServices/vaults", + "apiVersion": "2023-01-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": "[variables('identity')]", + "sku": { + "name": "RS0", + "tier": "Standard" + }, + "properties": { + "monitoringSettings": "[if(not(empty(parameters('monitoringSettings'))), parameters('monitoringSettings'), null())]", + "securitySettings": "[if(not(empty(parameters('securitySettings'))), parameters('securitySettings'), null())]", + "publicNetworkAccess": "[parameters('publicNetworkAccess')]" + } + }, + "rsv_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.RecoveryServices/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": [ + "rsv" + ] + }, + "rsv_diagnosticSettings": { + "copy": { + "name": "rsv_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.RecoveryServices/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": [ + "rsv" + ] + }, + "rsv_roleAssignments": { + "copy": { + "name": "rsv_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.RecoveryServices/vaults/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.RecoveryServices/vaults', 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": [ + "rsv" + ] + }, + "rsv_replicationFabrics": { + "copy": { + "name": "rsv_replicationFabrics", + "count": "[length(parameters('replicationFabrics'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-RSV-Fabric-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "recoveryVaultName": { + "value": "[parameters('name')]" + }, + "name": "[if(contains(parameters('replicationFabrics')[copyIndex()], 'name'), createObject('value', parameters('replicationFabrics')[copyIndex()].name), createObject('value', parameters('replicationFabrics')[copyIndex()].location))]", + "location": { + "value": "[parameters('replicationFabrics')[copyIndex()].location]" + }, + "replicationContainers": "[if(contains(parameters('replicationFabrics')[copyIndex()], 'replicationContainers'), createObject('value', parameters('replicationFabrics')[copyIndex()].replicationContainers), createObject('value', createArray()))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "9213187265421923503" + }, + "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.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Required. The recovery location the fabric represents." + } + }, + "name": { + "type": "string", + "defaultValue": "[parameters('location')]", + "metadata": { + "description": "Optional. The name of the fabric." + } + }, + "replicationContainers": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Replication containers to create." + } + } + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/replicationFabrics", + "apiVersion": "2022-10-01", + "name": "[format('{0}/{1}', parameters('recoveryVaultName'), parameters('name'))]", + "properties": { + "customDetails": { + "instanceType": "Azure", + "location": "[parameters('location')]" + } + } + }, + { + "copy": { + "name": "fabric_replicationContainers", + "count": "[length(parameters('replicationContainers'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-RCont-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('replicationContainers')[copyIndex()].name]" + }, + "recoveryVaultName": { + "value": "[parameters('recoveryVaultName')]" + }, + "replicationFabricName": { + "value": "[parameters('name')]" + }, + "replicationContainerMappings": "[if(contains(parameters('replicationContainers')[copyIndex()], 'replicationContainerMappings'), createObject('value', parameters('replicationContainers')[copyIndex()].replicationContainerMappings), createObject('value', createArray()))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "584392949528635994" + }, + "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.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "replicationFabricName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Replication Fabric. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the replication container." + } + }, + "replicationContainerMappings": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Replication containers mappings to create." + } + } + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers", + "apiVersion": "2022-10-01", + "name": "[format('{0}/{1}/{2}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('name'))]", + "properties": { + "providerSpecificInput": [ + { + "instanceType": "A2A" + } + ] + } + }, + { + "copy": { + "name": "fabric_container_containerMappings", + "count": "[length(parameters('replicationContainerMappings'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Map-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "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', ''))]", + "recoveryVaultName": { + "value": "[parameters('recoveryVaultName')]" + }, + "replicationFabricName": { + "value": "[parameters('replicationFabricName')]" + }, + "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', ''))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "8286726590589779511" + }, + "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.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "replicationFabricName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Replication Fabric. Required if the template is used in a standalone deployment." + } + }, + "sourceProtectionContainerName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent source Replication container. Required if the template is used in a standalone deployment." + } + }, + "targetProtectionContainerId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the target Replication container. Must be specified if targetContainerName is not. If specified, targetContainerFabricName and targetContainerName will be ignored." + } + }, + "targetContainerFabricName": { + "type": "string", + "defaultValue": "[parameters('replicationFabricName')]", + "metadata": { + "description": "Optional. Name of the fabric containing the target container. If targetProtectionContainerId is specified, this parameter will be ignored." + } + }, + "targetContainerName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the target container. Must be specified if targetProtectionContainerId is not. If targetProtectionContainerId is specified, this parameter will be ignored." + } + }, + "policyId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the replication policy. If defined, policyName will be ignored." + } + }, + "policyName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the replication policy. Will be ignored if policyId is also specified." + } + }, + "name": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The name of the replication container mapping. If not provided, it will be automatically generated as `-`." + } + } + }, + "variables": { + "policyResourceId": "[if(not(equals(parameters('policyId'), '')), parameters('policyId'), subscriptionResourceId('Microsoft.RecoveryServices/vaults/replicationPolicies', parameters('recoveryVaultName'), parameters('policyName')))]", + "targetProtectionContainerResourceId": "[if(not(equals(parameters('targetProtectionContainerId'), '')), parameters('targetProtectionContainerId'), subscriptionResourceId('Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers', parameters('recoveryVaultName'), parameters('targetContainerFabricName'), parameters('targetContainerName')))]", + "mappingName": "[if(not(empty(parameters('name'))), parameters('name'), format('{0}-{1}', parameters('sourceProtectionContainerName'), split(variables('targetProtectionContainerResourceId'), '/')[10]))]" + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings", + "apiVersion": "2022-10-01", + "name": "[format('{0}/{1}/{2}/{3}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('sourceProtectionContainerName'), variables('mappingName'))]", + "properties": { + "targetProtectionContainerId": "[variables('targetProtectionContainerResourceId')]", + "policyId": "[variables('policyResourceId')]", + "providerSpecificInput": { + "instanceType": "A2A" + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the replication container." + }, + "value": "[format('{0}/{1}/{2}/{3}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('sourceProtectionContainerName'), variables('mappingName'))]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the replication container." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings', split(format('{0}/{1}/{2}/{3}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('sourceProtectionContainerName'), variables('mappingName')), '/')[0], split(format('{0}/{1}/{2}/{3}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('sourceProtectionContainerName'), variables('mappingName')), '/')[1], split(format('{0}/{1}/{2}/{3}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('sourceProtectionContainerName'), variables('mappingName')), '/')[2], split(format('{0}/{1}/{2}/{3}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('sourceProtectionContainerName'), variables('mappingName')), '/')[3])]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the replication container was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers', split(format('{0}/{1}/{2}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('name')), '/')[0], split(format('{0}/{1}/{2}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('name')), '/')[1], split(format('{0}/{1}/{2}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('name')), '/')[2])]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the replication container." + }, + "value": "[format('{0}/{1}/{2}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('name'))]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the replication container." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers', split(format('{0}/{1}/{2}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('name')), '/')[0], split(format('{0}/{1}/{2}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('name')), '/')[1], split(format('{0}/{1}/{2}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('name')), '/')[2])]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the replication container was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.RecoveryServices/vaults/replicationFabrics', split(format('{0}/{1}', parameters('recoveryVaultName'), parameters('name')), '/')[0], split(format('{0}/{1}', parameters('recoveryVaultName'), parameters('name')), '/')[1])]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the replication fabric." + }, + "value": "[format('{0}/{1}', parameters('recoveryVaultName'), parameters('name'))]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the replication fabric." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/replicationFabrics', split(format('{0}/{1}', parameters('recoveryVaultName'), parameters('name')), '/')[0], split(format('{0}/{1}', parameters('recoveryVaultName'), parameters('name')), '/')[1])]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the replication fabric was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "rsv", + "rsv_replicationPolicies" + ] + }, + "rsv_replicationPolicies": { + "copy": { + "name": "rsv_replicationPolicies", + "count": "[length(parameters('replicationPolicies'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-RSV-Policy-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('replicationPolicies')[copyIndex()].name]" + }, + "recoveryVaultName": { + "value": "[parameters('name')]" + }, + "appConsistentFrequencyInMinutes": "[if(contains(parameters('replicationPolicies')[copyIndex()], 'appConsistentFrequencyInMinutes'), createObject('value', parameters('replicationPolicies')[copyIndex()].appConsistentFrequencyInMinutes), createObject('value', 60))]", + "crashConsistentFrequencyInMinutes": "[if(contains(parameters('replicationPolicies')[copyIndex()], 'crashConsistentFrequencyInMinutes'), createObject('value', parameters('replicationPolicies')[copyIndex()].crashConsistentFrequencyInMinutes), createObject('value', 5))]", + "multiVmSyncStatus": "[if(contains(parameters('replicationPolicies')[copyIndex()], 'multiVmSyncStatus'), createObject('value', parameters('replicationPolicies')[copyIndex()].multiVmSyncStatus), createObject('value', 'Enable'))]", + "recoveryPointHistory": "[if(contains(parameters('replicationPolicies')[copyIndex()], 'recoveryPointHistory'), createObject('value', parameters('replicationPolicies')[copyIndex()].recoveryPointHistory), createObject('value', 1440))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "12506498029720805552" + }, + "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.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the replication policy." + } + }, + "appConsistentFrequencyInMinutes": { + "type": "int", + "defaultValue": 60, + "metadata": { + "description": "Optional. The app consistent snapshot frequency (in minutes)." + } + }, + "crashConsistentFrequencyInMinutes": { + "type": "int", + "defaultValue": 5, + "metadata": { + "description": "Optional. The crash consistent snapshot frequency (in minutes)." + } + }, + "multiVmSyncStatus": { + "type": "string", + "defaultValue": "Enable", + "allowedValues": [ + "Enable", + "Disable" + ], + "metadata": { + "description": "Optional. A value indicating whether multi-VM sync has to be enabled." + } + }, + "recoveryPointHistory": { + "type": "int", + "defaultValue": 1440, + "metadata": { + "description": "Optional. The duration in minutes until which the recovery points need to be stored." + } + } + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/replicationPolicies", + "apiVersion": "2023-06-01", + "name": "[format('{0}/{1}', parameters('recoveryVaultName'), parameters('name'))]", + "properties": { + "providerSpecificInput": { + "instanceType": "A2A", + "appConsistentFrequencyInMinutes": "[parameters('appConsistentFrequencyInMinutes')]", + "crashConsistentFrequencyInMinutes": "[parameters('crashConsistentFrequencyInMinutes')]", + "multiVmSyncStatus": "[parameters('multiVmSyncStatus')]", + "recoveryPointHistory": "[parameters('recoveryPointHistory')]" + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the replication policy." + }, + "value": "[format('{0}/{1}', parameters('recoveryVaultName'), parameters('name'))]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the replication policy." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/replicationPolicies', split(format('{0}/{1}', parameters('recoveryVaultName'), parameters('name')), '/')[0], split(format('{0}/{1}', parameters('recoveryVaultName'), parameters('name')), '/')[1])]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the replication policy was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "rsv" + ] + }, + "rsv_backupStorageConfiguration": { + "condition": "[not(empty(parameters('backupStorageConfig')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-RSV-BackupStorageConfig', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "recoveryVaultName": { + "value": "[parameters('name')]" + }, + "storageModelType": { + "value": "[parameters('backupStorageConfig').storageModelType]" + }, + "crossRegionRestoreFlag": { + "value": "[parameters('backupStorageConfig').crossRegionRestoreFlag]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "16823125725342753814" + }, + "name": "Recovery Services Vault Backup Storage Config", + "description": "This module deploys a Recovery Service Vault Backup Storage Configuration.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "defaultValue": "vaultstorageconfig", + "metadata": { + "description": "Optional. The name of the backup storage config." + } + }, + "storageModelType": { + "type": "string", + "defaultValue": "GeoRedundant", + "allowedValues": [ + "GeoRedundant", + "LocallyRedundant", + "ReadAccessGeoZoneRedundant", + "ZoneRedundant" + ], + "metadata": { + "description": "Optional. Change Vault Storage Type (Works if vault has not registered any backup instance)." + } + }, + "crossRegionRestoreFlag": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Opt in details of Cross Region Restore feature." + } + } + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/backupstorageconfig", + "apiVersion": "2023-01-01", + "name": "[format('{0}/{1}', parameters('recoveryVaultName'), parameters('name'))]", + "properties": { + "storageModelType": "[parameters('storageModelType')]", + "crossRegionRestoreFlag": "[parameters('crossRegionRestoreFlag')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the backup storage config." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the backup storage config." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/backupstorageconfig', parameters('recoveryVaultName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the backup storage configuration was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "rsv" + ] + }, + "rsv_backupFabric_protectionContainers": { + "copy": { + "name": "rsv_backupFabric_protectionContainers", + "count": "[length(parameters('protectionContainers'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-RSV-ProtectionContainers-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "recoveryVaultName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('protectionContainers')[copyIndex()].name]" + }, + "sourceResourceId": { + "value": "[tryGet(parameters('protectionContainers')[copyIndex()], 'sourceResourceId')]" + }, + "friendlyName": { + "value": "[tryGet(parameters('protectionContainers')[copyIndex()], 'friendlyName')]" + }, + "backupManagementType": { + "value": "[tryGet(parameters('protectionContainers')[copyIndex()], 'backupManagementType')]" + }, + "containerType": { + "value": "[tryGet(parameters('protectionContainers')[copyIndex()], 'containerType')]" + }, + "protectedItems": "[if(contains(parameters('protectionContainers')[copyIndex()], 'protectedItems'), createObject('value', parameters('protectionContainers')[copyIndex()].protectedItems), createObject('value', createArray()))]", + "location": { + "value": "[parameters('location')]" + } + }, + "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": "5887508216739936022" + }, + "name": "Recovery Services Vault Protection Container", + "description": "This module deploys a Recovery Services Vault Protection Container.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Azure Recovery Service Vault Protection Container." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "backupManagementType": { + "type": "string", + "nullable": true, + "allowedValues": [ + "AzureBackupServer", + "AzureIaasVM", + "AzureSql", + "AzureStorage", + "AzureWorkload", + "DPM", + "DefaultBackup", + "Invalid", + "MAB" + ], + "metadata": { + "description": "Optional. Backup management type to execute the current Protection Container job." + } + }, + "sourceResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the target resource for the Protection Container." + } + }, + "friendlyName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Friendly name of the Protection Container." + } + }, + "protectedItems": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Protected items to register in the container." + } + }, + "containerType": { + "type": "string", + "nullable": true, + "allowedValues": [ + "AzureBackupServerContainer", + "AzureSqlContainer", + "GenericContainer", + "Microsoft.ClassicCompute/virtualMachines", + "Microsoft.Compute/virtualMachines", + "SQLAGWorkLoadContainer", + "StorageContainer", + "VMAppContainer", + "Windows" + ], + "metadata": { + "description": "Optional. Type of the container." + } + } + }, + "resources": { + "protectionContainer": { + "type": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers", + "apiVersion": "2023-01-01", + "name": "[format('{0}/Azure/{1}', parameters('recoveryVaultName'), parameters('name'))]", + "properties": { + "sourceResourceId": "[parameters('sourceResourceId')]", + "friendlyName": "[parameters('friendlyName')]", + "backupManagementType": "[parameters('backupManagementType')]", + "containerType": "[if(not(empty(parameters('containerType'))), parameters('containerType'), null())]" + } + }, + "protectionContainer_protectedItems": { + "copy": { + "name": "protectionContainer_protectedItems", + "count": "[length(parameters('protectedItems'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-ProtectedItem-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "policyId": { + "value": "[parameters('protectedItems')[copyIndex()].policyId]" + }, + "name": { + "value": "[parameters('protectedItems')[copyIndex()].name]" + }, + "protectedItemType": { + "value": "[parameters('protectedItems')[copyIndex()].protectedItemType]" + }, + "protectionContainerName": { + "value": "[format('{0}/Azure/{1}', parameters('recoveryVaultName'), parameters('name'))]" + }, + "recoveryVaultName": { + "value": "[parameters('recoveryVaultName')]" + }, + "sourceResourceId": { + "value": "[parameters('protectedItems')[copyIndex()].sourceResourceId]" + }, + "location": { + "value": "[parameters('location')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "15677187951825533891" + }, + "name": "Recovery Service Vaults Protection Container Protected Item", + "description": "This module deploys a Recovery Services Vault Protection Container Protected Item.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the resource." + } + }, + "protectionContainerName": { + "type": "string", + "metadata": { + "description": "Conditional. Name of the Azure Recovery Service Vault Protection Container. Required if the template is used in a standalone deployment." + } + }, + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "protectedItemType": { + "type": "string", + "allowedValues": [ + "AzureFileShareProtectedItem", + "AzureVmWorkloadSAPAseDatabase", + "AzureVmWorkloadSAPHanaDatabase", + "AzureVmWorkloadSQLDatabase", + "DPMProtectedItem", + "GenericProtectedItem", + "MabFileFolderProtectedItem", + "Microsoft.ClassicCompute/virtualMachines", + "Microsoft.Compute/virtualMachines", + "Microsoft.Sql/servers/databases" + ], + "metadata": { + "description": "Required. The backup item type." + } + }, + "policyId": { + "type": "string", + "metadata": { + "description": "Required. ID of the backup policy with which this item is backed up." + } + }, + "sourceResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the resource to back up." + } + } + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems", + "apiVersion": "2023-01-01", + "name": "[format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "protectedItemType": "[parameters('protectedItemType')]", + "policyId": "[parameters('policyId')]", + "sourceResourceId": "[parameters('sourceResourceId')]" + } + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the protected item was created in." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the protected item." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems', split(format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name')), '/')[0], split(format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name')), '/')[1], split(format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name')), '/')[2], split(format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name')), '/')[3])]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The Name of the protected item." + }, + "value": "[format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name'))]" + } + } + } + }, + "dependsOn": [ + "protectionContainer" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the Protection Container was created in." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Protection Container." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers', split(format('{0}/Azure/{1}', parameters('recoveryVaultName'), parameters('name')), '/')[0], split(format('{0}/Azure/{1}', parameters('recoveryVaultName'), parameters('name')), '/')[1], split(format('{0}/Azure/{1}', parameters('recoveryVaultName'), parameters('name')), '/')[2])]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The Name of the Protection Container." + }, + "value": "[format('{0}/Azure/{1}', parameters('recoveryVaultName'), parameters('name'))]" + } + } + } + }, + "dependsOn": [ + "rsv" + ] + }, + "rsv_backupPolicies": { + "copy": { + "name": "rsv_backupPolicies", + "count": "[length(parameters('backupPolicies'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-RSV-BackupPolicy-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "recoveryVaultName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('backupPolicies')[copyIndex()].name]" + }, + "properties": { + "value": "[parameters('backupPolicies')[copyIndex()].properties]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "3329904805287164035" + }, + "name": "Recovery Services Vault Backup Policies", + "description": "This module deploys a Recovery Services Vault Backup Policy.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Azure Recovery Service Vault Backup Policy." + } + }, + "properties": { + "type": "object", + "metadata": { + "description": "Required. Configuration of the Azure Recovery Service Vault Backup Policy." + } + } + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/backupPolicies", + "apiVersion": "2023-01-01", + "name": "[format('{0}/{1}', parameters('recoveryVaultName'), parameters('name'))]", + "properties": "[parameters('properties')]" + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the backup policy." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the backup policy." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/backupPolicies', parameters('recoveryVaultName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the backup policy was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "rsv" + ] + }, + "rsv_backupConfig": { + "condition": "[not(empty(parameters('backupConfig')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-RSV-BackupConfig', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "recoveryVaultName": { + "value": "[parameters('name')]" + }, + "name": "[if(contains(parameters('backupConfig'), 'name'), createObject('value', parameters('backupConfig').name), createObject('value', 'vaultconfig'))]", + "enhancedSecurityState": "[if(contains(parameters('backupConfig'), 'enhancedSecurityState'), createObject('value', parameters('backupConfig').enhancedSecurityState), createObject('value', 'Enabled'))]", + "resourceGuardOperationRequests": "[if(contains(parameters('backupConfig'), 'resourceGuardOperationRequests'), createObject('value', parameters('backupConfig').resourceGuardOperationRequests), createObject('value', createArray()))]", + "softDeleteFeatureState": "[if(contains(parameters('backupConfig'), 'softDeleteFeatureState'), createObject('value', parameters('backupConfig').softDeleteFeatureState), createObject('value', 'Enabled'))]", + "storageModelType": "[if(contains(parameters('backupConfig'), 'storageModelType'), createObject('value', parameters('backupConfig').storageModelType), createObject('value', 'GeoRedundant'))]", + "storageType": "[if(contains(parameters('backupConfig'), 'storageType'), createObject('value', parameters('backupConfig').storageType), createObject('value', 'GeoRedundant'))]", + "storageTypeState": "[if(contains(parameters('backupConfig'), 'storageTypeState'), createObject('value', parameters('backupConfig').storageTypeState), createObject('value', 'Locked'))]", + "isSoftDeleteFeatureStateEditable": "[if(contains(parameters('backupConfig'), 'isSoftDeleteFeatureStateEditable'), createObject('value', parameters('backupConfig').isSoftDeleteFeatureStateEditable), createObject('value', true()))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "15423985878725052790" + }, + "name": "Recovery Services Vault Backup Config", + "description": "This module deploys a Recovery Services Vault Backup Config.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "defaultValue": "vaultconfig", + "metadata": { + "description": "Optional. Name of the Azure Recovery Service Vault Backup Policy." + } + }, + "enhancedSecurityState": { + "type": "string", + "defaultValue": "Enabled", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "metadata": { + "description": "Optional. Enable this setting to protect hybrid backups against accidental deletes and add additional layer of authentication for critical operations." + } + }, + "resourceGuardOperationRequests": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. ResourceGuard Operation Requests." + } + }, + "softDeleteFeatureState": { + "type": "string", + "defaultValue": "Enabled", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "metadata": { + "description": "Optional. Enable this setting to protect backup data for Azure VM, SQL Server in Azure VM and SAP HANA in Azure VM from accidental deletes." + } + }, + "storageModelType": { + "type": "string", + "defaultValue": "GeoRedundant", + "allowedValues": [ + "GeoRedundant", + "LocallyRedundant", + "ReadAccessGeoZoneRedundant", + "ZoneRedundant" + ], + "metadata": { + "description": "Optional. Storage type." + } + }, + "storageType": { + "type": "string", + "defaultValue": "GeoRedundant", + "allowedValues": [ + "GeoRedundant", + "LocallyRedundant", + "ReadAccessGeoZoneRedundant", + "ZoneRedundant" + ], + "metadata": { + "description": "Optional. Storage type." + } + }, + "storageTypeState": { + "type": "string", + "defaultValue": "Locked", + "allowedValues": [ + "Locked", + "Unlocked" + ], + "metadata": { + "description": "Optional. Once a machine is registered against a resource, the storageTypeState is always Locked." + } + }, + "isSoftDeleteFeatureStateEditable": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Is soft delete feature state editable." + } + } + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/backupconfig", + "apiVersion": "2023-01-01", + "name": "[format('{0}/{1}', parameters('recoveryVaultName'), parameters('name'))]", + "properties": { + "enhancedSecurityState": "[parameters('enhancedSecurityState')]", + "resourceGuardOperationRequests": "[parameters('resourceGuardOperationRequests')]", + "softDeleteFeatureState": "[parameters('softDeleteFeatureState')]", + "storageModelType": "[parameters('storageModelType')]", + "storageType": "[parameters('storageType')]", + "storageTypeState": "[parameters('storageTypeState')]", + "isSoftDeleteFeatureStateEditable": "[parameters('isSoftDeleteFeatureStateEditable')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the backup config." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the backup config." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/backupconfig', parameters('recoveryVaultName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the backup config was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "rsv" + ] + }, + "rsv_replicationAlertSettings": { + "condition": "[not(empty(parameters('replicationAlertSettings')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-RSV-replicationAlertSettings', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "defaultAlertSetting" + }, + "recoveryVaultName": { + "value": "[parameters('name')]" + }, + "customEmailAddresses": "[if(contains(parameters('replicationAlertSettings'), 'customEmailAddresses'), createObject('value', parameters('replicationAlertSettings').customEmailAddresses), createObject('value', createArray()))]", + "locale": "[if(contains(parameters('replicationAlertSettings'), 'locale'), createObject('value', parameters('replicationAlertSettings').locale), createObject('value', ''))]", + "sendToOwners": "[if(contains(parameters('replicationAlertSettings'), 'sendToOwners'), createObject('value', parameters('replicationAlertSettings').sendToOwners), createObject('value', 'Send'))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "15609344101830369541" + }, + "name": "Recovery Services Vault Replication Alert Settings", + "description": "This module deploys a Recovery Services Vault Replication Alert Settings.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "defaultValue": "defaultAlertSetting", + "metadata": { + "description": "Optional. The name of the replication Alert Setting." + } + }, + "customEmailAddresses": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Comma separated list of custom email address for sending alert emails." + } + }, + "locale": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The locale for the email notification." + } + }, + "sendToOwners": { + "type": "string", + "defaultValue": "Send", + "allowedValues": [ + "DoNotSend", + "Send" + ], + "metadata": { + "description": "Optional. The value indicating whether to send email to subscription administrator." + } + } + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/replicationAlertSettings", + "apiVersion": "2022-10-01", + "name": "[format('{0}/{1}', parameters('recoveryVaultName'), parameters('name'))]", + "properties": { + "customEmailAddresses": "[if(not(empty(parameters('customEmailAddresses'))), parameters('customEmailAddresses'), null())]", + "locale": "[parameters('locale')]", + "sendToOwners": "[parameters('sendToOwners')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the replication Alert Setting." + }, + "value": "[parameters('name')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the replication alert setting was created." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the replication alert setting." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/replicationAlertSettings', parameters('recoveryVaultName'), parameters('name'))]" + } + } + } + }, + "dependsOn": [ + "rsv" + ] + }, + "rsv_privateEndpoints": { + "copy": { + "name": "rsv_privateEndpoints", + "count": "[length(coalesce(parameters('privateEndpoints'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-RSV-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "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.RecoveryServices/vaults', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'AzureSiteRecovery'), copyIndex()))]" + }, + "privateLinkServiceConnections": "[if(not(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections'), true())), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.RecoveryServices/vaults', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'AzureSiteRecovery'), copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.RecoveryServices/vaults', parameters('name')), 'groupIds', createArray(coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'AzureSiteRecovery')))))), createObject('value', null()))]", + "manualPrivateLinkServiceConnections": "[if(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections'), true()), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.RecoveryServices/vaults', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'AzureSiteRecovery'), copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.RecoveryServices/vaults', parameters('name')), 'groupIds', createArray(coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'AzureSiteRecovery')), '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'))]" + }, + "privateDnsZoneGroupName": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneGroupName')]" + }, + "privateDnsZoneResourceIds": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneResourceIds')]" + }, + "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.24.24.22086", + "templateHash": "2592884001616184297" + }, + "name": "Private Endpoints", + "description": "This module deploys a Private Endpoint.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "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." + } + }, + "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 + }, + "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", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "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", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "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 + } + }, + "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." + } + }, + "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", + "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." + } + }, + "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": { + "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": "2023-07-01", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.4.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" + } + } + } + } + }, + "privateEndpoint": { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-04-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(parameters('roleAssignments'), 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)]", + "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": [ + "privateEndpoint" + ] + }, + "privateEndpoint_privateDnsZoneGroup": { + "condition": "[not(empty(parameters('privateDnsZoneResourceIds')))]", + "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": "[coalesce(parameters('privateDnsZoneGroupName'), 'default')]" + }, + "privateDNSResourceIds": { + "value": "[coalesce(parameters('privateDnsZoneResourceIds'), createArray())]" + }, + "privateEndpointName": { + "value": "[parameters('name')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "9321937464667207030" + }, + "name": "Private Endpoint Private DNS Zone Groups", + "description": "This module deploys a Private Endpoint Private DNS Zone Group.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "privateEndpointName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent private endpoint. Required if the template is used in a standalone deployment." + } + }, + "privateDNSResourceIds": { + "type": "array", + "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." + } + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the private DNS zone group." + } + } + }, + "variables": { + "copy": [ + { + "name": "privateDnsZoneConfigs", + "count": "[length(parameters('privateDNSResourceIds'))]", + "input": { + "name": "[last(split(parameters('privateDNSResourceIds')[copyIndex('privateDnsZoneConfigs')], '/'))]", + "properties": { + "privateDnsZoneId": "[parameters('privateDNSResourceIds')[copyIndex('privateDnsZoneConfigs')]]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2023-04-01", + "name": "[format('{0}/{1}', parameters('privateEndpointName'), parameters('name'))]", + "properties": { + "privateDnsZoneConfigs": "[variables('privateDnsZoneConfigs')]" + } + } + ], + "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-04-01', 'full').location]" + }, + "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])]" + } + } + } + }, + "dependsOn": [ + "rsv" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the recovery services vault." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the recovery services vault was created in." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The Name of the recovery services vault." + }, + "value": "[parameters('name')]" + }, + "systemAssignedMIPrincipalId": { + "type": "string", + "metadata": { + "description": "The principal ID of the system assigned identity." + }, + "value": "[coalesce(tryGet(tryGet(reference('rsv', '2023-01-01', 'full'), 'identity'), 'principalId'), '')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('rsv', '2023-01-01', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/recovery-services/vault/replication-alert-setting/README.md b/avm/res/recovery-services/vault/replication-alert-setting/README.md new file mode 100644 index 0000000000..0b33f8f4e3 --- /dev/null +++ b/avm/res/recovery-services/vault/replication-alert-setting/README.md @@ -0,0 +1,97 @@ +# Recovery Services Vault Replication Alert Settings `[Microsoft.RecoveryServices/vaults/replicationAlertSettings]` + +This module deploys a Recovery Services Vault Replication Alert Settings. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.RecoveryServices/vaults/replicationAlertSettings` | [2022-10-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2022-10-01/vaults/replicationAlertSettings) | + +## Parameters + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`recoveryVaultName`](#parameter-recoveryvaultname) | string | The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`customEmailAddresses`](#parameter-customemailaddresses) | array | Comma separated list of custom email address for sending alert emails. | +| [`locale`](#parameter-locale) | string | The locale for the email notification. | +| [`name`](#parameter-name) | string | The name of the replication Alert Setting. | +| [`sendToOwners`](#parameter-sendtoowners) | string | The value indicating whether to send email to subscription administrator. | + +### Parameter: `recoveryVaultName` + +The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `customEmailAddresses` + +Comma separated list of custom email address for sending alert emails. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `locale` + +The locale for the email notification. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `name` + +The name of the replication Alert Setting. + +- Required: No +- Type: string +- Default: `'defaultAlertSetting'` + +### Parameter: `sendToOwners` + +The value indicating whether to send email to subscription administrator. + +- Required: No +- Type: string +- Default: `'Send'` +- Allowed: + ```Bicep + [ + 'DoNotSend' + 'Send' + ] + ``` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the replication Alert Setting. | +| `resourceGroupName` | string | The name of the resource group the replication alert setting was created. | +| `resourceId` | string | The resource ID of the replication alert setting. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/recovery-services/vault/replication-alert-setting/main.bicep b/avm/res/recovery-services/vault/replication-alert-setting/main.bicep new file mode 100644 index 0000000000..cc2036feba --- /dev/null +++ b/avm/res/recovery-services/vault/replication-alert-setting/main.bicep @@ -0,0 +1,45 @@ +metadata name = 'Recovery Services Vault Replication Alert Settings' +metadata description = 'This module deploys a Recovery Services Vault Replication Alert Settings.' +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('Optional. The name of the replication Alert Setting.') +param name string = 'defaultAlertSetting' + +@description('Optional. Comma separated list of custom email address for sending alert emails.') +param customEmailAddresses array = [] + +@description('Optional. The locale for the email notification.') +param locale string = '' + +@description('Optional. The value indicating whether to send email to subscription administrator.') +@allowed([ + 'DoNotSend' + 'Send' +]) +param sendToOwners string = 'Send' + +resource recoveryVault 'Microsoft.RecoveryServices/vaults@2023-01-01' existing = { + name: recoveryVaultName +} + +resource replicationAlertSettings 'Microsoft.RecoveryServices/vaults/replicationAlertSettings@2022-10-01' = { + name: name + parent: recoveryVault + properties: { + customEmailAddresses: !empty(customEmailAddresses) ? customEmailAddresses : null + locale: locale + sendToOwners: sendToOwners + } +} + +@description('The name of the replication Alert Setting.') +output name string = replicationAlertSettings.name + +@description('The name of the resource group the replication alert setting was created.') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the replication alert setting.') +output resourceId string = replicationAlertSettings.id diff --git a/avm/res/recovery-services/vault/replication-alert-setting/main.json b/avm/res/recovery-services/vault/replication-alert-setting/main.json new file mode 100644 index 0000000000..a3659c2417 --- /dev/null +++ b/avm/res/recovery-services/vault/replication-alert-setting/main.json @@ -0,0 +1,89 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "15609344101830369541" + }, + "name": "Recovery Services Vault Replication Alert Settings", + "description": "This module deploys a Recovery Services Vault Replication Alert Settings.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "defaultValue": "defaultAlertSetting", + "metadata": { + "description": "Optional. The name of the replication Alert Setting." + } + }, + "customEmailAddresses": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Comma separated list of custom email address for sending alert emails." + } + }, + "locale": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The locale for the email notification." + } + }, + "sendToOwners": { + "type": "string", + "defaultValue": "Send", + "allowedValues": [ + "DoNotSend", + "Send" + ], + "metadata": { + "description": "Optional. The value indicating whether to send email to subscription administrator." + } + } + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/replicationAlertSettings", + "apiVersion": "2022-10-01", + "name": "[format('{0}/{1}', parameters('recoveryVaultName'), parameters('name'))]", + "properties": { + "customEmailAddresses": "[if(not(empty(parameters('customEmailAddresses'))), parameters('customEmailAddresses'), null())]", + "locale": "[parameters('locale')]", + "sendToOwners": "[parameters('sendToOwners')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the replication Alert Setting." + }, + "value": "[parameters('name')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the replication alert setting was created." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the replication alert setting." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/replicationAlertSettings', parameters('recoveryVaultName'), parameters('name'))]" + } + } +} \ No newline at end of file diff --git a/avm/res/recovery-services/vault/replication-fabric/README.md b/avm/res/recovery-services/vault/replication-fabric/README.md new file mode 100644 index 0000000000..b2164e9a9a --- /dev/null +++ b/avm/res/recovery-services/vault/replication-fabric/README.md @@ -0,0 +1,90 @@ +# Recovery Services Vault Replication Fabrics `[Microsoft.RecoveryServices/vaults/replicationFabrics]` + +This module deploys a Replication Fabric for Azure to Azure disaster recovery scenario of Azure Site Recovery. + +> Note: this module currently support only the `instanceType: 'Azure'` scenario. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.RecoveryServices/vaults/replicationFabrics` | [2022-10-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2022-10-01/vaults/replicationFabrics) | +| `Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers` | [2022-10-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2022-10-01/vaults/replicationFabrics/replicationProtectionContainers) | +| `Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings` | [2022-10-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2022-10-01/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`location`](#parameter-location) | string | The recovery location the fabric represents. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`recoveryVaultName`](#parameter-recoveryvaultname) | string | The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | The name of the fabric. | +| [`replicationContainers`](#parameter-replicationcontainers) | array | Replication containers to create. | + +### Parameter: `location` + +The recovery location the fabric represents. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `recoveryVaultName` + +The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `name` + +The name of the fabric. + +- Required: No +- Type: string +- Default: `[parameters('location')]` + +### Parameter: `replicationContainers` + +Replication containers to create. + +- Required: No +- Type: array +- Default: `[]` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the replication fabric. | +| `resourceGroupName` | string | The name of the resource group the replication fabric was created in. | +| `resourceId` | string | The resource ID of the replication fabric. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/recovery-services/vault/replication-fabric/main.bicep b/avm/res/recovery-services/vault/replication-fabric/main.bicep new file mode 100644 index 0000000000..5156981ed4 --- /dev/null +++ b/avm/res/recovery-services/vault/replication-fabric/main.bicep @@ -0,0 +1,49 @@ +metadata name = 'Recovery Services Vault Replication Fabrics' +metadata description = '''This module deploys a Replication Fabric for Azure to Azure disaster recovery scenario of Azure Site Recovery. + +> Note: this module currently support only the `instanceType: 'Azure'` scenario.''' +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.') +param location string = resourceGroup().location + +@description('Optional. The name of the fabric.') +param name string = location + +@description('Optional. Replication containers to create.') +param replicationContainers array = [] + +resource replicationFabric 'Microsoft.RecoveryServices/vaults/replicationFabrics@2022-10-01' = { + name: '${recoveryVaultName}/${name}' + properties: { + customDetails: { + instanceType: 'Azure' + location: location + } + } +} + +module fabric_replicationContainers 'replication-protection-container/main.bicep' = [for (container, index) in replicationContainers: { + name: '${deployment().name}-RCont-${index}' + params: { + name: container.name + recoveryVaultName: recoveryVaultName + replicationFabricName: name + replicationContainerMappings: contains(container, 'replicationContainerMappings') ? container.replicationContainerMappings : [] + } + dependsOn: [ + replicationFabric + ] +}] + +@description('The name of the replication fabric.') +output name string = replicationFabric.name + +@description('The resource ID of the replication fabric.') +output resourceId string = replicationFabric.id + +@description('The name of the resource group the replication fabric was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/avm/res/recovery-services/vault/replication-fabric/main.json b/avm/res/recovery-services/vault/replication-fabric/main.json new file mode 100644 index 0000000000..5be50536e8 --- /dev/null +++ b/avm/res/recovery-services/vault/replication-fabric/main.json @@ -0,0 +1,340 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "9213187265421923503" + }, + "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.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Required. The recovery location the fabric represents." + } + }, + "name": { + "type": "string", + "defaultValue": "[parameters('location')]", + "metadata": { + "description": "Optional. The name of the fabric." + } + }, + "replicationContainers": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Replication containers to create." + } + } + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/replicationFabrics", + "apiVersion": "2022-10-01", + "name": "[format('{0}/{1}', parameters('recoveryVaultName'), parameters('name'))]", + "properties": { + "customDetails": { + "instanceType": "Azure", + "location": "[parameters('location')]" + } + } + }, + { + "copy": { + "name": "fabric_replicationContainers", + "count": "[length(parameters('replicationContainers'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-RCont-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('replicationContainers')[copyIndex()].name]" + }, + "recoveryVaultName": { + "value": "[parameters('recoveryVaultName')]" + }, + "replicationFabricName": { + "value": "[parameters('name')]" + }, + "replicationContainerMappings": "[if(contains(parameters('replicationContainers')[copyIndex()], 'replicationContainerMappings'), createObject('value', parameters('replicationContainers')[copyIndex()].replicationContainerMappings), createObject('value', createArray()))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "584392949528635994" + }, + "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.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "replicationFabricName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Replication Fabric. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the replication container." + } + }, + "replicationContainerMappings": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Replication containers mappings to create." + } + } + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers", + "apiVersion": "2022-10-01", + "name": "[format('{0}/{1}/{2}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('name'))]", + "properties": { + "providerSpecificInput": [ + { + "instanceType": "A2A" + } + ] + } + }, + { + "copy": { + "name": "fabric_container_containerMappings", + "count": "[length(parameters('replicationContainerMappings'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Map-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "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', ''))]", + "recoveryVaultName": { + "value": "[parameters('recoveryVaultName')]" + }, + "replicationFabricName": { + "value": "[parameters('replicationFabricName')]" + }, + "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', ''))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "8286726590589779511" + }, + "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.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "replicationFabricName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Replication Fabric. Required if the template is used in a standalone deployment." + } + }, + "sourceProtectionContainerName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent source Replication container. Required if the template is used in a standalone deployment." + } + }, + "targetProtectionContainerId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the target Replication container. Must be specified if targetContainerName is not. If specified, targetContainerFabricName and targetContainerName will be ignored." + } + }, + "targetContainerFabricName": { + "type": "string", + "defaultValue": "[parameters('replicationFabricName')]", + "metadata": { + "description": "Optional. Name of the fabric containing the target container. If targetProtectionContainerId is specified, this parameter will be ignored." + } + }, + "targetContainerName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the target container. Must be specified if targetProtectionContainerId is not. If targetProtectionContainerId is specified, this parameter will be ignored." + } + }, + "policyId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the replication policy. If defined, policyName will be ignored." + } + }, + "policyName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the replication policy. Will be ignored if policyId is also specified." + } + }, + "name": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The name of the replication container mapping. If not provided, it will be automatically generated as `-`." + } + } + }, + "variables": { + "policyResourceId": "[if(not(equals(parameters('policyId'), '')), parameters('policyId'), subscriptionResourceId('Microsoft.RecoveryServices/vaults/replicationPolicies', parameters('recoveryVaultName'), parameters('policyName')))]", + "targetProtectionContainerResourceId": "[if(not(equals(parameters('targetProtectionContainerId'), '')), parameters('targetProtectionContainerId'), subscriptionResourceId('Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers', parameters('recoveryVaultName'), parameters('targetContainerFabricName'), parameters('targetContainerName')))]", + "mappingName": "[if(not(empty(parameters('name'))), parameters('name'), format('{0}-{1}', parameters('sourceProtectionContainerName'), split(variables('targetProtectionContainerResourceId'), '/')[10]))]" + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings", + "apiVersion": "2022-10-01", + "name": "[format('{0}/{1}/{2}/{3}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('sourceProtectionContainerName'), variables('mappingName'))]", + "properties": { + "targetProtectionContainerId": "[variables('targetProtectionContainerResourceId')]", + "policyId": "[variables('policyResourceId')]", + "providerSpecificInput": { + "instanceType": "A2A" + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the replication container." + }, + "value": "[format('{0}/{1}/{2}/{3}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('sourceProtectionContainerName'), variables('mappingName'))]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the replication container." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings', split(format('{0}/{1}/{2}/{3}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('sourceProtectionContainerName'), variables('mappingName')), '/')[0], split(format('{0}/{1}/{2}/{3}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('sourceProtectionContainerName'), variables('mappingName')), '/')[1], split(format('{0}/{1}/{2}/{3}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('sourceProtectionContainerName'), variables('mappingName')), '/')[2], split(format('{0}/{1}/{2}/{3}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('sourceProtectionContainerName'), variables('mappingName')), '/')[3])]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the replication container was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers', split(format('{0}/{1}/{2}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('name')), '/')[0], split(format('{0}/{1}/{2}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('name')), '/')[1], split(format('{0}/{1}/{2}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('name')), '/')[2])]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the replication container." + }, + "value": "[format('{0}/{1}/{2}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('name'))]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the replication container." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers', split(format('{0}/{1}/{2}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('name')), '/')[0], split(format('{0}/{1}/{2}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('name')), '/')[1], split(format('{0}/{1}/{2}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('name')), '/')[2])]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the replication container was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.RecoveryServices/vaults/replicationFabrics', split(format('{0}/{1}', parameters('recoveryVaultName'), parameters('name')), '/')[0], split(format('{0}/{1}', parameters('recoveryVaultName'), parameters('name')), '/')[1])]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the replication fabric." + }, + "value": "[format('{0}/{1}', parameters('recoveryVaultName'), parameters('name'))]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the replication fabric." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/replicationFabrics', split(format('{0}/{1}', parameters('recoveryVaultName'), parameters('name')), '/')[0], split(format('{0}/{1}', parameters('recoveryVaultName'), parameters('name')), '/')[1])]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the replication fabric was created in." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/README.md b/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/README.md new file mode 100644 index 0000000000..7b6a116e1e --- /dev/null +++ b/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/README.md @@ -0,0 +1,87 @@ +# Recovery Services Vault Replication Fabric Replication Protection Containers `[Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers]` + +This module deploys a Recovery Services Vault Replication Protection Container. + +> **Note**: this version of the module only supports the `instanceType: 'A2A'` scenario. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers` | [2022-10-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2022-10-01/vaults/replicationFabrics/replicationProtectionContainers) | +| `Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings` | [2022-10-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2022-10-01/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | The name of the replication container. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`recoveryVaultName`](#parameter-recoveryvaultname) | string | The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment. | +| [`replicationFabricName`](#parameter-replicationfabricname) | string | The name of the parent Replication Fabric. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`replicationContainerMappings`](#parameter-replicationcontainermappings) | array | Replication containers mappings to create. | + +### Parameter: `name` + +The name of the replication container. + +- Required: Yes +- Type: string + +### Parameter: `recoveryVaultName` + +The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `replicationFabricName` + +The name of the parent Replication Fabric. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `replicationContainerMappings` + +Replication containers mappings to create. + +- Required: No +- Type: array +- Default: `[]` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the replication container. | +| `resourceGroupName` | string | The name of the resource group the replication container was created in. | +| `resourceId` | string | The resource ID of the replication container. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/main.bicep b/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/main.bicep new file mode 100644 index 0000000000..4e23d2b5d3 --- /dev/null +++ b/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/main.bicep @@ -0,0 +1,55 @@ +metadata name = 'Recovery Services Vault Replication Fabric Replication Protection Containers' +metadata description = '''This module deploys a Recovery Services Vault Replication Protection Container. + +> **Note**: this version of the module only supports the `instanceType: 'A2A'` scenario.''' +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('Conditional. The name of the parent Replication Fabric. Required if the template is used in a standalone deployment.') +param replicationFabricName string + +@description('Required. The name of the replication container.') +param name string + +@description('Optional. Replication containers mappings to create.') +param replicationContainerMappings array = [] + +resource replicationContainer 'Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers@2022-10-01' = { + name: '${recoveryVaultName}/${replicationFabricName}/${name}' + properties: { + providerSpecificInput: [ + { + instanceType: 'A2A' + } + ] + } +} + +module fabric_container_containerMappings 'replication-protection-container-mapping/main.bicep' = [for (mapping, index) in replicationContainerMappings: { + name: '${deployment().name}-Map-${index}' + params: { + name: contains(mapping, 'name') ? mapping.name : '' + policyId: contains(mapping, 'policyId') ? mapping.policyId : '' + policyName: contains(mapping, 'policyName') ? mapping.policyName : '' + recoveryVaultName: recoveryVaultName + replicationFabricName: replicationFabricName + sourceProtectionContainerName: name + targetProtectionContainerId: contains(mapping, 'targetProtectionContainerId') ? mapping.targetProtectionContainerId : '' + targetContainerFabricName: contains(mapping, 'targetContainerFabricName') ? mapping.targetContainerFabricName : replicationFabricName + targetContainerName: contains(mapping, 'targetContainerName') ? mapping.targetContainerName : '' + } + dependsOn: [ + replicationContainer + ] +}] + +@description('The name of the replication container.') +output name string = replicationContainer.name + +@description('The resource ID of the replication container.') +output resourceId string = replicationContainer.id + +@description('The name of the resource group the replication container was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/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 new file mode 100644 index 0000000000..78784a2039 --- /dev/null +++ b/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/main.json @@ -0,0 +1,231 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "584392949528635994" + }, + "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.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "replicationFabricName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Replication Fabric. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the replication container." + } + }, + "replicationContainerMappings": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Replication containers mappings to create." + } + } + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers", + "apiVersion": "2022-10-01", + "name": "[format('{0}/{1}/{2}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('name'))]", + "properties": { + "providerSpecificInput": [ + { + "instanceType": "A2A" + } + ] + } + }, + { + "copy": { + "name": "fabric_container_containerMappings", + "count": "[length(parameters('replicationContainerMappings'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Map-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "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', ''))]", + "recoveryVaultName": { + "value": "[parameters('recoveryVaultName')]" + }, + "replicationFabricName": { + "value": "[parameters('replicationFabricName')]" + }, + "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', ''))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "8286726590589779511" + }, + "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.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "replicationFabricName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Replication Fabric. Required if the template is used in a standalone deployment." + } + }, + "sourceProtectionContainerName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent source Replication container. Required if the template is used in a standalone deployment." + } + }, + "targetProtectionContainerId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the target Replication container. Must be specified if targetContainerName is not. If specified, targetContainerFabricName and targetContainerName will be ignored." + } + }, + "targetContainerFabricName": { + "type": "string", + "defaultValue": "[parameters('replicationFabricName')]", + "metadata": { + "description": "Optional. Name of the fabric containing the target container. If targetProtectionContainerId is specified, this parameter will be ignored." + } + }, + "targetContainerName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the target container. Must be specified if targetProtectionContainerId is not. If targetProtectionContainerId is specified, this parameter will be ignored." + } + }, + "policyId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the replication policy. If defined, policyName will be ignored." + } + }, + "policyName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the replication policy. Will be ignored if policyId is also specified." + } + }, + "name": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The name of the replication container mapping. If not provided, it will be automatically generated as `-`." + } + } + }, + "variables": { + "policyResourceId": "[if(not(equals(parameters('policyId'), '')), parameters('policyId'), subscriptionResourceId('Microsoft.RecoveryServices/vaults/replicationPolicies', parameters('recoveryVaultName'), parameters('policyName')))]", + "targetProtectionContainerResourceId": "[if(not(equals(parameters('targetProtectionContainerId'), '')), parameters('targetProtectionContainerId'), subscriptionResourceId('Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers', parameters('recoveryVaultName'), parameters('targetContainerFabricName'), parameters('targetContainerName')))]", + "mappingName": "[if(not(empty(parameters('name'))), parameters('name'), format('{0}-{1}', parameters('sourceProtectionContainerName'), split(variables('targetProtectionContainerResourceId'), '/')[10]))]" + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings", + "apiVersion": "2022-10-01", + "name": "[format('{0}/{1}/{2}/{3}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('sourceProtectionContainerName'), variables('mappingName'))]", + "properties": { + "targetProtectionContainerId": "[variables('targetProtectionContainerResourceId')]", + "policyId": "[variables('policyResourceId')]", + "providerSpecificInput": { + "instanceType": "A2A" + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the replication container." + }, + "value": "[format('{0}/{1}/{2}/{3}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('sourceProtectionContainerName'), variables('mappingName'))]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the replication container." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings', split(format('{0}/{1}/{2}/{3}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('sourceProtectionContainerName'), variables('mappingName')), '/')[0], split(format('{0}/{1}/{2}/{3}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('sourceProtectionContainerName'), variables('mappingName')), '/')[1], split(format('{0}/{1}/{2}/{3}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('sourceProtectionContainerName'), variables('mappingName')), '/')[2], split(format('{0}/{1}/{2}/{3}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('sourceProtectionContainerName'), variables('mappingName')), '/')[3])]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the replication container was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers', split(format('{0}/{1}/{2}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('name')), '/')[0], split(format('{0}/{1}/{2}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('name')), '/')[1], split(format('{0}/{1}/{2}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('name')), '/')[2])]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the replication container." + }, + "value": "[format('{0}/{1}/{2}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('name'))]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the replication container." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers', split(format('{0}/{1}/{2}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('name')), '/')[0], split(format('{0}/{1}/{2}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('name')), '/')[1], split(format('{0}/{1}/{2}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('name')), '/')[2])]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the replication container was created in." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/replication-protection-container-mapping/README.md b/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/replication-protection-container-mapping/README.md new file mode 100644 index 0000000000..18b3a09a62 --- /dev/null +++ b/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/replication-protection-container-mapping/README.md @@ -0,0 +1,126 @@ +# Recovery Services Vault Replication Fabric Replication Protection Container Replication Protection Container Mappings `[Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings]` + +This module deploys a Recovery Services Vault (RSV) Replication Protection Container Mapping. + +> **Note**: this version of the module only supports the `instanceType: 'A2A'` scenario. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings` | [2022-10-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2022-10-01/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings) | + +## Parameters + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`recoveryVaultName`](#parameter-recoveryvaultname) | string | The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment. | +| [`replicationFabricName`](#parameter-replicationfabricname) | string | The name of the parent Replication Fabric. Required if the template is used in a standalone deployment. | +| [`sourceProtectionContainerName`](#parameter-sourceprotectioncontainername) | string | The name of the parent source Replication container. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | The name of the replication container mapping. If not provided, it will be automatically generated as `-`. | +| [`policyId`](#parameter-policyid) | string | Resource ID of the replication policy. If defined, policyName will be ignored. | +| [`policyName`](#parameter-policyname) | string | Name of the replication policy. Will be ignored if policyId is also specified. | +| [`targetContainerFabricName`](#parameter-targetcontainerfabricname) | string | Name of the fabric containing the target container. If targetProtectionContainerId is specified, this parameter will be ignored. | +| [`targetContainerName`](#parameter-targetcontainername) | string | Name of the target container. Must be specified if targetProtectionContainerId is not. If targetProtectionContainerId is specified, this parameter will be ignored. | +| [`targetProtectionContainerId`](#parameter-targetprotectioncontainerid) | string | Resource ID of the target Replication container. Must be specified if targetContainerName is not. If specified, targetContainerFabricName and targetContainerName will be ignored. | + +### Parameter: `recoveryVaultName` + +The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `replicationFabricName` + +The name of the parent Replication Fabric. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `sourceProtectionContainerName` + +The name of the parent source Replication container. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `name` + +The name of the replication container mapping. If not provided, it will be automatically generated as `-`. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `policyId` + +Resource ID of the replication policy. If defined, policyName will be ignored. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `policyName` + +Name of the replication policy. Will be ignored if policyId is also specified. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `targetContainerFabricName` + +Name of the fabric containing the target container. If targetProtectionContainerId is specified, this parameter will be ignored. + +- Required: No +- Type: string +- Default: `[parameters('replicationFabricName')]` + +### Parameter: `targetContainerName` + +Name of the target container. Must be specified if targetProtectionContainerId is not. If targetProtectionContainerId is specified, this parameter will be ignored. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `targetProtectionContainerId` + +Resource ID of the target Replication container. Must be specified if targetContainerName is not. If specified, targetContainerFabricName and targetContainerName will be ignored. + +- Required: No +- Type: string +- Default: `''` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the replication container. | +| `resourceGroupName` | string | The name of the resource group the replication container was created in. | +| `resourceId` | string | The resource ID of the replication container. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/replication-protection-container-mapping/main.bicep b/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/replication-protection-container-mapping/main.bicep new file mode 100644 index 0000000000..1e0fc30ec9 --- /dev/null +++ b/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/replication-protection-container-mapping/main.bicep @@ -0,0 +1,56 @@ +metadata name = 'Recovery Services Vault Replication Fabric Replication Protection Container Replication Protection Container Mappings' +metadata description = '''This module deploys a Recovery Services Vault (RSV) Replication Protection Container Mapping. + +> **Note**: this version of the module only supports the `instanceType: 'A2A'` scenario.''' +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('Conditional. The name of the parent Replication Fabric. Required if the template is used in a standalone deployment.') +param replicationFabricName string + +@description('Conditional. The name of the parent source Replication container. Required if the template is used in a standalone deployment.') +param sourceProtectionContainerName string + +@description('Optional. Resource ID of the target Replication container. Must be specified if targetContainerName is not. If specified, targetContainerFabricName and targetContainerName will be ignored.') +param targetProtectionContainerId string = '' + +@description('Optional. Name of the fabric containing the target container. If targetProtectionContainerId is specified, this parameter will be ignored.') +param targetContainerFabricName string = replicationFabricName + +@description('Optional. Name of the target container. Must be specified if targetProtectionContainerId is not. If targetProtectionContainerId is specified, this parameter will be ignored.') +param targetContainerName string = '' + +@description('Optional. Resource ID of the replication policy. If defined, policyName will be ignored.') +param policyId string = '' + +@description('Optional. Name of the replication policy. Will be ignored if policyId is also specified.') +param policyName string = '' + +@description('Optional. The name of the replication container mapping. If not provided, it will be automatically generated as `-`.') +param name string = '' + +var policyResourceId = policyId != '' ? policyId : subscriptionResourceId('Microsoft.RecoveryServices/vaults/replicationPolicies', recoveryVaultName, policyName) +var targetProtectionContainerResourceId = targetProtectionContainerId != '' ? targetProtectionContainerId : subscriptionResourceId('Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers', recoveryVaultName, targetContainerFabricName, targetContainerName) +var mappingName = !empty(name) ? name : '${sourceProtectionContainerName}-${split(targetProtectionContainerResourceId, '/')[10]}' + +resource replicationContainer 'Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings@2022-10-01' = { + name: '${recoveryVaultName}/${replicationFabricName}/${sourceProtectionContainerName}/${mappingName}' + properties: { + targetProtectionContainerId: targetProtectionContainerResourceId + policyId: policyResourceId + providerSpecificInput: { + instanceType: 'A2A' + } + } +} + +@description('The name of the replication container.') +output name string = replicationContainer.name + +@description('The resource ID of the replication container.') +output resourceId string = replicationContainer.id + +@description('The name of the resource group the replication container was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/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 new file mode 100644 index 0000000000..2c633c2461 --- /dev/null +++ b/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/replication-protection-container-mapping/main.json @@ -0,0 +1,118 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "8286726590589779511" + }, + "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.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "replicationFabricName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Replication Fabric. Required if the template is used in a standalone deployment." + } + }, + "sourceProtectionContainerName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent source Replication container. Required if the template is used in a standalone deployment." + } + }, + "targetProtectionContainerId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the target Replication container. Must be specified if targetContainerName is not. If specified, targetContainerFabricName and targetContainerName will be ignored." + } + }, + "targetContainerFabricName": { + "type": "string", + "defaultValue": "[parameters('replicationFabricName')]", + "metadata": { + "description": "Optional. Name of the fabric containing the target container. If targetProtectionContainerId is specified, this parameter will be ignored." + } + }, + "targetContainerName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the target container. Must be specified if targetProtectionContainerId is not. If targetProtectionContainerId is specified, this parameter will be ignored." + } + }, + "policyId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the replication policy. If defined, policyName will be ignored." + } + }, + "policyName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the replication policy. Will be ignored if policyId is also specified." + } + }, + "name": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The name of the replication container mapping. If not provided, it will be automatically generated as `-`." + } + } + }, + "variables": { + "policyResourceId": "[if(not(equals(parameters('policyId'), '')), parameters('policyId'), subscriptionResourceId('Microsoft.RecoveryServices/vaults/replicationPolicies', parameters('recoveryVaultName'), parameters('policyName')))]", + "targetProtectionContainerResourceId": "[if(not(equals(parameters('targetProtectionContainerId'), '')), parameters('targetProtectionContainerId'), subscriptionResourceId('Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers', parameters('recoveryVaultName'), parameters('targetContainerFabricName'), parameters('targetContainerName')))]", + "mappingName": "[if(not(empty(parameters('name'))), parameters('name'), format('{0}-{1}', parameters('sourceProtectionContainerName'), split(variables('targetProtectionContainerResourceId'), '/')[10]))]" + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings", + "apiVersion": "2022-10-01", + "name": "[format('{0}/{1}/{2}/{3}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('sourceProtectionContainerName'), variables('mappingName'))]", + "properties": { + "targetProtectionContainerId": "[variables('targetProtectionContainerResourceId')]", + "policyId": "[variables('policyResourceId')]", + "providerSpecificInput": { + "instanceType": "A2A" + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the replication container." + }, + "value": "[format('{0}/{1}/{2}/{3}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('sourceProtectionContainerName'), variables('mappingName'))]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the replication container." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings', split(format('{0}/{1}/{2}/{3}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('sourceProtectionContainerName'), variables('mappingName')), '/')[0], split(format('{0}/{1}/{2}/{3}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('sourceProtectionContainerName'), variables('mappingName')), '/')[1], split(format('{0}/{1}/{2}/{3}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('sourceProtectionContainerName'), variables('mappingName')), '/')[2], split(format('{0}/{1}/{2}/{3}', parameters('recoveryVaultName'), parameters('replicationFabricName'), parameters('sourceProtectionContainerName'), variables('mappingName')), '/')[3])]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the replication container was created in." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/recovery-services/vault/replication-policy/README.md b/avm/res/recovery-services/vault/replication-policy/README.md new file mode 100644 index 0000000000..67f1af8480 --- /dev/null +++ b/avm/res/recovery-services/vault/replication-policy/README.md @@ -0,0 +1,112 @@ +# Recovery Services Vault Replication Policies `[Microsoft.RecoveryServices/vaults/replicationPolicies]` + +This module deploys a Recovery Services Vault Replication Policy for Disaster Recovery scenario. + +> **Note**: this version of the module only supports the `instanceType: 'A2A'` scenario. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.RecoveryServices/vaults/replicationPolicies` | [2023-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/vaults/replicationPolicies) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | The name of the replication policy. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`recoveryVaultName`](#parameter-recoveryvaultname) | string | The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`appConsistentFrequencyInMinutes`](#parameter-appconsistentfrequencyinminutes) | int | The app consistent snapshot frequency (in minutes). | +| [`crashConsistentFrequencyInMinutes`](#parameter-crashconsistentfrequencyinminutes) | int | The crash consistent snapshot frequency (in minutes). | +| [`multiVmSyncStatus`](#parameter-multivmsyncstatus) | string | A value indicating whether multi-VM sync has to be enabled. | +| [`recoveryPointHistory`](#parameter-recoverypointhistory) | int | The duration in minutes until which the recovery points need to be stored. | + +### Parameter: `name` + +The name of the replication policy. + +- Required: Yes +- Type: string + +### Parameter: `recoveryVaultName` + +The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `appConsistentFrequencyInMinutes` + +The app consistent snapshot frequency (in minutes). + +- Required: No +- Type: int +- Default: `60` + +### Parameter: `crashConsistentFrequencyInMinutes` + +The crash consistent snapshot frequency (in minutes). + +- Required: No +- Type: int +- Default: `5` + +### Parameter: `multiVmSyncStatus` + +A value indicating whether multi-VM sync has to be enabled. + +- Required: No +- Type: string +- Default: `'Enable'` +- Allowed: + ```Bicep + [ + 'Disable' + 'Enable' + ] + ``` + +### Parameter: `recoveryPointHistory` + +The duration in minutes until which the recovery points need to be stored. + +- Required: No +- Type: int +- Default: `1440` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the replication policy. | +| `resourceGroupName` | string | The name of the resource group the replication policy was created in. | +| `resourceId` | string | The resource ID of the replication policy. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/recovery-services/vault/replication-policy/main.bicep b/avm/res/recovery-services/vault/replication-policy/main.bicep new file mode 100644 index 0000000000..ae2ff4bf97 --- /dev/null +++ b/avm/res/recovery-services/vault/replication-policy/main.bicep @@ -0,0 +1,48 @@ +metadata name = 'Recovery Services Vault Replication Policies' +metadata description = '''This module deploys a Recovery Services Vault Replication Policy for Disaster Recovery scenario. + +> **Note**: this version of the module only supports the `instanceType: 'A2A'` scenario.''' +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 name of the replication policy.') +param name string + +@description('Optional. The app consistent snapshot frequency (in minutes).') +param appConsistentFrequencyInMinutes int = 60 + +@description('Optional. The crash consistent snapshot frequency (in minutes).') +param crashConsistentFrequencyInMinutes int = 5 + +@description('Optional. A value indicating whether multi-VM sync has to be enabled.') +@allowed([ + 'Enable' + 'Disable' +]) +param multiVmSyncStatus string = 'Enable' + +@description('Optional. The duration in minutes until which the recovery points need to be stored.') +param recoveryPointHistory int = 1440 + +resource replicationPolicy 'Microsoft.RecoveryServices/vaults/replicationPolicies@2023-06-01' = { + name: '${recoveryVaultName}/${name}' + properties: { + providerSpecificInput: { + instanceType: 'A2A' + appConsistentFrequencyInMinutes: appConsistentFrequencyInMinutes + crashConsistentFrequencyInMinutes: crashConsistentFrequencyInMinutes + multiVmSyncStatus: multiVmSyncStatus + recoveryPointHistory: recoveryPointHistory + } + } +} +@description('The name of the replication policy.') +output name string = replicationPolicy.name + +@description('The resource ID of the replication policy.') +output resourceId string = replicationPolicy.id + +@description('The name of the resource group the replication policy was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/avm/res/recovery-services/vault/replication-policy/main.json b/avm/res/recovery-services/vault/replication-policy/main.json new file mode 100644 index 0000000000..e67e01104b --- /dev/null +++ b/avm/res/recovery-services/vault/replication-policy/main.json @@ -0,0 +1,99 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "12506498029720805552" + }, + "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.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the replication policy." + } + }, + "appConsistentFrequencyInMinutes": { + "type": "int", + "defaultValue": 60, + "metadata": { + "description": "Optional. The app consistent snapshot frequency (in minutes)." + } + }, + "crashConsistentFrequencyInMinutes": { + "type": "int", + "defaultValue": 5, + "metadata": { + "description": "Optional. The crash consistent snapshot frequency (in minutes)." + } + }, + "multiVmSyncStatus": { + "type": "string", + "defaultValue": "Enable", + "allowedValues": [ + "Enable", + "Disable" + ], + "metadata": { + "description": "Optional. A value indicating whether multi-VM sync has to be enabled." + } + }, + "recoveryPointHistory": { + "type": "int", + "defaultValue": 1440, + "metadata": { + "description": "Optional. The duration in minutes until which the recovery points need to be stored." + } + } + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/replicationPolicies", + "apiVersion": "2023-06-01", + "name": "[format('{0}/{1}', parameters('recoveryVaultName'), parameters('name'))]", + "properties": { + "providerSpecificInput": { + "instanceType": "A2A", + "appConsistentFrequencyInMinutes": "[parameters('appConsistentFrequencyInMinutes')]", + "crashConsistentFrequencyInMinutes": "[parameters('crashConsistentFrequencyInMinutes')]", + "multiVmSyncStatus": "[parameters('multiVmSyncStatus')]", + "recoveryPointHistory": "[parameters('recoveryPointHistory')]" + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the replication policy." + }, + "value": "[format('{0}/{1}', parameters('recoveryVaultName'), parameters('name'))]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the replication policy." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/replicationPolicies', split(format('{0}/{1}', parameters('recoveryVaultName'), parameters('name')), '/')[0], split(format('{0}/{1}', parameters('recoveryVaultName'), parameters('name')), '/')[1])]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the replication policy was created in." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/recovery-services/vault/tests/e2e/defaults/main.test.bicep b/avm/res/recovery-services/vault/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..3444eae1ee --- /dev/null +++ b/avm/res/recovery-services/vault/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,62 @@ +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}-recoveryservices.vaults-${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 = 'rsvmin' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + enableTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + replicationAlertSettings: { + customEmailAddresses: [ + 'test.user@testcompany.com' + ] + locale: 'en-US' + sendToOwners: 'Send' + } + securitySettings: { + immutabilitySettings: { + state: 'Unlocked' + } + } + } +}] diff --git a/avm/res/recovery-services/vault/tests/e2e/dr/main.test.bicep b/avm/res/recovery-services/vault/tests/e2e/dr/main.test.bicep new file mode 100644 index 0000000000..f372f3c6e7 --- /dev/null +++ b/avm/res/recovery-services/vault/tests/e2e/dr/main.test.bicep @@ -0,0 +1,110 @@ +targetScope = 'subscription' + +metadata name = 'Test case for disaster recovery enabled' +metadata description = 'This instance deploys the module with disaster recovery enabled.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-recoveryservices.vaults-${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 = 'rsvdr' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +// ============== // +// Test Execution // +// ============== // +var rsvName = '${namePrefix}${serviceShort}001' +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + enableTelemetry: enableDefaultTelemetry + name: rsvName + replicationFabrics: [ + { + location: 'NorthEurope' + replicationContainers: [ + { + name: 'ne-container1' + replicationContainerMappings: [ + { + policyName: 'Default_values' + targetContainerName: 'pluto' + targetProtectionContainerId: '${resourceGroup.id}/providers/Microsoft.RecoveryServices/vaults/${rsvName}/replicationFabrics/NorthEurope/replicationProtectionContainers/ne-container2' + } + ] + } + { + name: 'ne-container2' + replicationContainerMappings: [ + { + policyName: 'Default_values' + targetContainerFabricName: 'WE-2' + targetContainerName: 'we-container1' + } + ] + } + ] + } + { + location: 'WestEurope' + name: 'WE-2' + replicationContainers: [ + { + name: 'we-container1' + replicationContainerMappings: [ + { + policyName: 'Default_values' + targetContainerFabricName: 'NorthEurope' + targetContainerName: 'ne-container2' + } + ] + } + ] + } + ] + replicationPolicies: [ + { + name: 'Default_values' + } + { + appConsistentFrequencyInMinutes: 240 + crashConsistentFrequencyInMinutes: 7 + multiVmSyncStatus: 'Disable' + name: 'Custom_values' + recoveryPointHistory: 2880 + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/recovery-services/vault/tests/e2e/max/dependencies.bicep b/avm/res/recovery-services/vault/tests/e2e/max/dependencies.bicep new file mode 100644 index 0000000000..12b8653f54 --- /dev/null +++ b/avm/res/recovery-services/vault/tests/e2e/max/dependencies.bicep @@ -0,0 +1,63 @@ +@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 + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +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) + } + } + ] + } +} + +resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { + name: 'privatelink.siterecovery.windowsazure.com' + location: 'global' + + resource virtualNetworkLinks 'virtualNetworkLinks@2020-06-01' = { + name: '${virtualNetwork.name}-vnetlink' + location: 'global' + properties: { + virtualNetwork: { + id: virtualNetwork.id + } + registrationEnabled: false + } + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].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 + +@description('The resource ID of the created Private DNS Zone.') +output privateDNSZoneResourceId string = privateDNSZone.id diff --git a/avm/res/recovery-services/vault/tests/e2e/max/main.test.bicep b/avm/res/recovery-services/vault/tests/e2e/max/main.test.bicep new file mode 100644 index 0000000000..1232ad832e --- /dev/null +++ b/avm/res/recovery-services/vault/tests/e2e/max/main.test.bicep @@ -0,0 +1,433 @@ +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}-recoveryservices.vaults-${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 = 'rsvmax' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + location: resourceLocation + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-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 + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + enableTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + backupConfig: { + enhancedSecurityState: 'Disabled' + softDeleteFeatureState: 'Disabled' + } + backupPolicies: [ + { + name: 'VMpolicy' + properties: { + backupManagementType: 'AzureIaasVM' + instantRPDetails: {} + instantRpRetentionRangeInDays: 2 + protectedItemsCount: 0 + retentionPolicy: { + dailySchedule: { + retentionDuration: { + count: 180 + durationType: 'Days' + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + } + monthlySchedule: { + retentionDuration: { + count: 60 + durationType: 'Months' + } + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + } + retentionPolicyType: 'LongTermRetentionPolicy' + weeklySchedule: { + daysOfTheWeek: [ + 'Sunday' + ] + retentionDuration: { + count: 12 + durationType: 'Weeks' + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + } + yearlySchedule: { + monthsOfYear: [ + 'January' + ] + retentionDuration: { + count: 10 + durationType: 'Years' + } + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + } + } + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunFrequency: 'Daily' + scheduleRunTimes: [ + '2019-11-07T07:00:00Z' + ] + scheduleWeeklyFrequency: 0 + } + timeZone: 'UTC' + } + } + { + name: 'sqlpolicy' + properties: { + backupManagementType: 'AzureWorkload' + protectedItemsCount: 0 + settings: { + isCompression: true + issqlcompression: true + timeZone: 'UTC' + } + subProtectionPolicy: [ + { + policyType: 'Full' + retentionPolicy: { + monthlySchedule: { + retentionDuration: { + count: 60 + durationType: 'Months' + } + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T22:00:00Z' + ] + } + retentionPolicyType: 'LongTermRetentionPolicy' + weeklySchedule: { + daysOfTheWeek: [ + 'Sunday' + ] + retentionDuration: { + count: 104 + durationType: 'Weeks' + } + retentionTimes: [ + '2019-11-07T22:00:00Z' + ] + } + yearlySchedule: { + monthsOfYear: [ + 'January' + ] + retentionDuration: { + count: 10 + durationType: 'Years' + } + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T22:00:00Z' + ] + } + } + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunDays: [ + 'Sunday' + ] + scheduleRunFrequency: 'Weekly' + scheduleRunTimes: [ + '2019-11-07T22:00:00Z' + ] + scheduleWeeklyFrequency: 0 + } + } + { + policyType: 'Differential' + retentionPolicy: { + retentionDuration: { + count: 30 + durationType: 'Days' + } + retentionPolicyType: 'SimpleRetentionPolicy' + } + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunDays: [ + 'Monday' + ] + scheduleRunFrequency: 'Weekly' + scheduleRunTimes: [ + '2017-03-07T02:00:00Z' + ] + scheduleWeeklyFrequency: 0 + } + } + { + policyType: 'Log' + retentionPolicy: { + retentionDuration: { + count: 15 + durationType: 'Days' + } + retentionPolicyType: 'SimpleRetentionPolicy' + } + schedulePolicy: { + scheduleFrequencyInMins: 120 + schedulePolicyType: 'LogSchedulePolicy' + } + } + ] + workLoadType: 'SQLDataBase' + } + } + { + name: 'filesharepolicy' + properties: { + backupManagementType: 'AzureStorage' + protectedItemsCount: 0 + retentionPolicy: { + dailySchedule: { + retentionDuration: { + count: 30 + durationType: 'Days' + } + retentionTimes: [ + '2019-11-07T04:30:00Z' + ] + } + retentionPolicyType: 'LongTermRetentionPolicy' + } + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunFrequency: 'Daily' + scheduleRunTimes: [ + '2019-11-07T04:30:00Z' + ] + scheduleWeeklyFrequency: 0 + } + timeZone: 'UTC' + workloadType: 'AzureFileShare' + } + } + ] + backupStorageConfig: { + crossRegionRestoreFlag: true + storageModelType: 'GeoRedundant' + } + replicationAlertSettings: { + customEmailAddresses: [ + 'test.user@testcompany.com' + ] + locale: 'en-US' + sendToOwners: 'Send' + } + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + privateEndpoints: [ + { + ipConfigurations: [ + { + name: 'myIpConfig-1' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-tel1' + privateIPAddress: '10.0.0.10' + } + } + { + name: 'myIPconfig-2' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-prot2' + privateIPAddress: '10.0.0.11' + } + } + { + name: 'myIPconfig-3' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-srs1' + privateIPAddress: '10.0.0.12' + } + } + { + name: 'myIPconfig-4' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-rcm1' + privateIPAddress: '10.0.0.13' + } + } + { + name: 'myIPconfig-5' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-id1' + privateIPAddress: '10.0.0.14' + } + } + ] + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + ] + 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' + } + ] + monitoringSettings: { + azureMonitorAlertSettings: { + alertsForAllJobFailures: 'Enabled' + } + classicAlertSettings: { + alertsForCriticalOperations: 'Enabled' + } + } + securitySettings: { + immutabilitySettings: { + state: 'Unlocked' + } + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/recovery-services/vault/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/recovery-services/vault/tests/e2e/waf-aligned/dependencies.bicep new file mode 100644 index 0000000000..12b8653f54 --- /dev/null +++ b/avm/res/recovery-services/vault/tests/e2e/waf-aligned/dependencies.bicep @@ -0,0 +1,63 @@ +@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 + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +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) + } + } + ] + } +} + +resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { + name: 'privatelink.siterecovery.windowsazure.com' + location: 'global' + + resource virtualNetworkLinks 'virtualNetworkLinks@2020-06-01' = { + name: '${virtualNetwork.name}-vnetlink' + location: 'global' + properties: { + virtualNetwork: { + id: virtualNetwork.id + } + registrationEnabled: false + } + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].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 + +@description('The resource ID of the created Private DNS Zone.') +output privateDNSZoneResourceId string = privateDNSZone.id diff --git a/avm/res/recovery-services/vault/tests/e2e/waf-aligned/main.test.bicep b/avm/res/recovery-services/vault/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..22605d1d30 --- /dev/null +++ b/avm/res/recovery-services/vault/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,416 @@ +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}-recoveryservices.vaults-${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 = 'rsvwaf' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + location: resourceLocation + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-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 + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + enableTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + backupConfig: { + enhancedSecurityState: 'Disabled' + softDeleteFeatureState: 'Disabled' + } + backupPolicies: [ + { + name: 'VMpolicy' + properties: { + backupManagementType: 'AzureIaasVM' + instantRPDetails: {} + instantRpRetentionRangeInDays: 2 + protectedItemsCount: 0 + retentionPolicy: { + dailySchedule: { + retentionDuration: { + count: 180 + durationType: 'Days' + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + } + monthlySchedule: { + retentionDuration: { + count: 60 + durationType: 'Months' + } + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + } + retentionPolicyType: 'LongTermRetentionPolicy' + weeklySchedule: { + daysOfTheWeek: [ + 'Sunday' + ] + retentionDuration: { + count: 12 + durationType: 'Weeks' + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + } + yearlySchedule: { + monthsOfYear: [ + 'January' + ] + retentionDuration: { + count: 10 + durationType: 'Years' + } + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + } + } + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunFrequency: 'Daily' + scheduleRunTimes: [ + '2019-11-07T07:00:00Z' + ] + scheduleWeeklyFrequency: 0 + } + timeZone: 'UTC' + } + } + { + name: 'sqlpolicy' + properties: { + backupManagementType: 'AzureWorkload' + protectedItemsCount: 0 + settings: { + isCompression: true + issqlcompression: true + timeZone: 'UTC' + } + subProtectionPolicy: [ + { + policyType: 'Full' + retentionPolicy: { + monthlySchedule: { + retentionDuration: { + count: 60 + durationType: 'Months' + } + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T22:00:00Z' + ] + } + retentionPolicyType: 'LongTermRetentionPolicy' + weeklySchedule: { + daysOfTheWeek: [ + 'Sunday' + ] + retentionDuration: { + count: 104 + durationType: 'Weeks' + } + retentionTimes: [ + '2019-11-07T22:00:00Z' + ] + } + yearlySchedule: { + monthsOfYear: [ + 'January' + ] + retentionDuration: { + count: 10 + durationType: 'Years' + } + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T22:00:00Z' + ] + } + } + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunDays: [ + 'Sunday' + ] + scheduleRunFrequency: 'Weekly' + scheduleRunTimes: [ + '2019-11-07T22:00:00Z' + ] + scheduleWeeklyFrequency: 0 + } + } + { + policyType: 'Differential' + retentionPolicy: { + retentionDuration: { + count: 30 + durationType: 'Days' + } + retentionPolicyType: 'SimpleRetentionPolicy' + } + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunDays: [ + 'Monday' + ] + scheduleRunFrequency: 'Weekly' + scheduleRunTimes: [ + '2017-03-07T02:00:00Z' + ] + scheduleWeeklyFrequency: 0 + } + } + { + policyType: 'Log' + retentionPolicy: { + retentionDuration: { + count: 15 + durationType: 'Days' + } + retentionPolicyType: 'SimpleRetentionPolicy' + } + schedulePolicy: { + scheduleFrequencyInMins: 120 + schedulePolicyType: 'LogSchedulePolicy' + } + } + ] + workLoadType: 'SQLDataBase' + } + } + { + name: 'filesharepolicy' + properties: { + backupManagementType: 'AzureStorage' + protectedItemsCount: 0 + retentionPolicy: { + dailySchedule: { + retentionDuration: { + count: 30 + durationType: 'Days' + } + retentionTimes: [ + '2019-11-07T04:30:00Z' + ] + } + retentionPolicyType: 'LongTermRetentionPolicy' + } + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunFrequency: 'Daily' + scheduleRunTimes: [ + '2019-11-07T04:30:00Z' + ] + scheduleWeeklyFrequency: 0 + } + timeZone: 'UTC' + workloadType: 'AzureFileShare' + } + } + ] + backupStorageConfig: { + crossRegionRestoreFlag: true + storageModelType: 'GeoRedundant' + } + replicationAlertSettings: { + customEmailAddresses: [ + 'test.user@testcompany.com' + ] + locale: 'en-US' + sendToOwners: 'Send' + } + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + privateEndpoints: [ + { + ipConfigurations: [ + { + name: 'myIpConfig-1' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-tel1' + privateIPAddress: '10.0.0.10' + } + } + { + name: 'myIPconfig-2' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-prot2' + privateIPAddress: '10.0.0.11' + } + } + { + name: 'myIPconfig-3' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-srs1' + privateIPAddress: '10.0.0.12' + } + } + { + name: 'myIPconfig-4' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-rcm1' + privateIPAddress: '10.0.0.13' + } + } + { + name: 'myIPconfig-5' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-id1' + privateIPAddress: '10.0.0.14' + } + } + ] + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + ] + monitoringSettings: { + azureMonitorAlertSettings: { + alertsForAllJobFailures: 'Enabled' + } + classicAlertSettings: { + alertsForCriticalOperations: 'Enabled' + } + } + securitySettings: { + immutabilitySettings: { + state: 'Unlocked' + } + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/recovery-services/vault/version.json b/avm/res/recovery-services/vault/version.json new file mode 100644 index 0000000000..7fa401bdf7 --- /dev/null +++ b/avm/res/recovery-services/vault/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.1", + "pathFilters": [ + "./main.json" + ] +} From 8d53ec44204347db31c1081796fc85964c455eba Mon Sep 17 00:00:00 2001 From: Alexander Sehr Date: Wed, 20 Mar 2024 10:00:40 +0100 Subject: [PATCH 43/73] fix: Updated MSI Storage output to convention (#1245) ## Description Updated MSI Storage output to convention ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.storage.storage-account](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.storage.storage-account.yml/badge.svg?branch=users%2Falsehr%2FmsiOutput_storage&event=workflow_dispatch)](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.storage.storage-account.yml) | --- avm/res/storage/storage-account/main.bicep | 2 +- avm/res/storage/storage-account/main.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/avm/res/storage/storage-account/main.bicep b/avm/res/storage/storage-account/main.bicep index 4ad5eaca32..f8cc6f0c9a 100644 --- a/avm/res/storage/storage-account/main.bicep +++ b/avm/res/storage/storage-account/main.bicep @@ -492,7 +492,7 @@ output resourceGroupName string = resourceGroup().name output primaryBlobEndpoint string = !empty(blobServices) && contains(blobServices, 'containers') ? reference('Microsoft.Storage/storageAccounts/${storageAccount.name}', '2019-04-01').primaryEndpoints.blob : '' @description('The principal ID of the system assigned identity.') -output systemAssignedMIPrincipalId string = (managedIdentities.?systemAssigned ?? false) ? storageAccount.identity.?principalId : '' +output systemAssignedMIPrincipalId string = storageAccount.?identity.?principalId ?? '' @description('The location the resource was deployed into.') output location string = storageAccount.location diff --git a/avm/res/storage/storage-account/main.json b/avm/res/storage/storage-account/main.json index 12560b4a3b..0180a0b231 100644 --- a/avm/res/storage/storage-account/main.json +++ b/avm/res/storage/storage-account/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "8715806181703033501" + "templateHash": "16595339509600711048" }, "name": "Storage Accounts", "description": "This module deploys a Storage Account.", @@ -4611,7 +4611,7 @@ "metadata": { "description": "The principal ID of the system assigned identity." }, - "value": "[if(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), tryGet(reference('storageAccount', '2022-09-01', 'full').identity, 'principalId'), '')]" + "value": "[coalesce(tryGet(tryGet(reference('storageAccount', '2022-09-01', 'full'), 'identity'), 'principalId'), '')]" }, "location": { "type": "string", From 20e32b5d23bbeb8200cfad6c73207f25de33624a Mon Sep 17 00:00:00 2001 From: Alexander Sehr Date: Wed, 20 Mar 2024 10:36:19 +0100 Subject: [PATCH 44/73] fix: Removed remaining CARML references from readmes (#1340) ## Description Removed remaining CARML references from readmes cc: @jtracey93 ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.key-vault.vault](https://github.com/AlexanderSehr/bicep-registry-modules/actions/workflows/avm.res.key-vault.vault.yml/badge.svg?branch=users%2Falsehr%2FreadmeCarmlRemoval&event=workflow_dispatch)](https://github.com/AlexanderSehr/bicep-registry-modules/actions/workflows/avm.res.key-vault.vault.yml) | --------- Co-authored-by: Erika Gressi <56914614+eriqua@users.noreply.github.com> --- .../configuration-store/README.md | 2 +- .../automation/automation-account/README.md | 2 +- avm/res/batch/batch-account/README.md | 2 +- avm/res/cache/redis/README.md | 2 +- avm/res/cognitive-services/account/README.md | 2 +- avm/res/compute/virtual-machine/README.md | 2 +- avm/res/container-registry/registry/README.md | 2 +- .../managed-cluster/README.md | 2 +- avm/res/data-factory/factory/README.md | 2 +- avm/res/databricks/workspace/README.md | 2 +- .../host-pool/README.md | 2 +- .../workspace/README.md | 2 +- .../document-db/database-account/README.md | 2 +- avm/res/event-grid/domain/README.md | 2 +- avm/res/event-grid/namespace/README.md | 2 +- avm/res/event-grid/topic/README.md | 2 +- avm/res/event-hub/namespace/README.md | 2 +- avm/res/insights/private-link-scope/README.md | 2 +- avm/res/key-vault/vault/README.md | 2 +- .../extension/README.md | 2 +- .../workspace/README.md | 4 ++-- avm/res/network/azure-firewall/README.md | 2 +- avm/res/network/bastion-host/README.md | 2 +- avm/res/network/nat-gateway/README.md | 2 +- .../network/virtual-network-gateway/README.md | 2 +- .../operational-insights/workspace/README.md | 2 +- avm/res/purview/account/README.md | 4 ++-- avm/res/search/search-service/README.md | 2 +- avm/res/service-bus/namespace/README.md | 2 +- avm/res/signal-r-service/signal-r/README.md | 4 ++-- .../signal-r-service/web-pub-sub/README.md | 4 ++-- avm/res/sql/server/README.md | 2 +- avm/res/storage/storage-account/README.md | 2 +- avm/res/synapse/private-link-hub/README.md | 4 ++-- avm/res/synapse/workspace/README.md | 4 ++-- avm/res/web/site/README.md | 2 +- avm/res/web/site/slot/README.md | 2 +- avm/res/web/static-site/README.md | 2 +- .../sharedScripts/Set-ModuleReadMe.ps1 | 24 +++++++++---------- 39 files changed, 56 insertions(+), 56 deletions(-) diff --git a/avm/res/app-configuration/configuration-store/README.md b/avm/res/app-configuration/configuration-store/README.md index 8149f4a56b..da6911a272 100644 --- a/avm/res/app-configuration/configuration-store/README.md +++ b/avm/res/app-configuration/configuration-store/README.md @@ -1428,7 +1428,7 @@ Tags of the resource. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/automation/automation-account/README.md b/avm/res/automation/automation-account/README.md index 7453918030..5f85d48d81 100644 --- a/avm/res/automation/automation-account/README.md +++ b/avm/res/automation/automation-account/README.md @@ -1932,7 +1932,7 @@ List of variables to be created in the automation account. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/batch/batch-account/README.md b/avm/res/batch/batch-account/README.md index 1ea59e9346..131c5571fc 100644 --- a/avm/res/batch/batch-account/README.md +++ b/avm/res/batch/batch-account/README.md @@ -1537,7 +1537,7 @@ Tags of the resource. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/cache/redis/README.md b/avm/res/cache/redis/README.md index 11b99c963d..4414d3a7b6 100644 --- a/avm/res/cache/redis/README.md +++ b/avm/res/cache/redis/README.md @@ -1387,7 +1387,7 @@ If the zoneRedundant parameter is true, replicas will be provisioned in the avai ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/cognitive-services/account/README.md b/avm/res/cognitive-services/account/README.md index 7829d5f201..7fb0da5818 100644 --- a/avm/res/cognitive-services/account/README.md +++ b/avm/res/cognitive-services/account/README.md @@ -1718,7 +1718,7 @@ The storage accounts for this resource. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/compute/virtual-machine/README.md b/avm/res/compute/virtual-machine/README.md index f8e55e541d..628d64515c 100644 --- a/avm/res/compute/virtual-machine/README.md +++ b/avm/res/compute/virtual-machine/README.md @@ -3197,7 +3197,7 @@ Do not provide a value! This date value is used to generate a registration token ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/container-registry/registry/README.md b/avm/res/container-registry/registry/README.md index 12a6dca930..c9c60eb79c 100644 --- a/avm/res/container-registry/registry/README.md +++ b/avm/res/container-registry/registry/README.md @@ -1571,7 +1571,7 @@ Whether or not zone redundancy is enabled for this container registry. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/container-service/managed-cluster/README.md b/avm/res/container-service/managed-cluster/README.md index 55d31f23c1..13cfd48fce 100644 --- a/avm/res/container-service/managed-cluster/README.md +++ b/avm/res/container-service/managed-cluster/README.md @@ -3223,7 +3223,7 @@ Specifies whether the webApplicationRoutingEnabled add-on is enabled or not. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/data-factory/factory/README.md b/avm/res/data-factory/factory/README.md index c66b9c79f3..420af9f1e4 100644 --- a/avm/res/data-factory/factory/README.md +++ b/avm/res/data-factory/factory/README.md @@ -1335,7 +1335,7 @@ Tags of the resource. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/databricks/workspace/README.md b/avm/res/databricks/workspace/README.md index b82707c649..278713c94b 100644 --- a/avm/res/databricks/workspace/README.md +++ b/avm/res/databricks/workspace/README.md @@ -1513,7 +1513,7 @@ Address prefix for Managed virtual network. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/desktop-virtualization/host-pool/README.md b/avm/res/desktop-virtualization/host-pool/README.md index c38e99d1ea..c064356ace 100644 --- a/avm/res/desktop-virtualization/host-pool/README.md +++ b/avm/res/desktop-virtualization/host-pool/README.md @@ -1297,7 +1297,7 @@ Do not provide a value! This date value is used to generate a registration token ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/desktop-virtualization/workspace/README.md b/avm/res/desktop-virtualization/workspace/README.md index 614a16878a..f8592993aa 100644 --- a/avm/res/desktop-virtualization/workspace/README.md +++ b/avm/res/desktop-virtualization/workspace/README.md @@ -1105,7 +1105,7 @@ Tags of the resource. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/document-db/database-account/README.md b/avm/res/document-db/database-account/README.md index 00937cf54e..5f13c53560 100644 --- a/avm/res/document-db/database-account/README.md +++ b/avm/res/document-db/database-account/README.md @@ -3479,7 +3479,7 @@ Tags of the Database Account resource. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/event-grid/domain/README.md b/avm/res/event-grid/domain/README.md index 229f56e444..14374d14a5 100644 --- a/avm/res/event-grid/domain/README.md +++ b/avm/res/event-grid/domain/README.md @@ -1175,7 +1175,7 @@ The topic names which are associated with the domain. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/event-grid/namespace/README.md b/avm/res/event-grid/namespace/README.md index 62df5825ff..7ce215883e 100644 --- a/avm/res/event-grid/namespace/README.md +++ b/avm/res/event-grid/namespace/README.md @@ -2176,7 +2176,7 @@ Indicates if Topic Spaces Configuration is enabled for the namespace. This enabl ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/event-grid/topic/README.md b/avm/res/event-grid/topic/README.md index a8e91be495..2126d9c209 100644 --- a/avm/res/event-grid/topic/README.md +++ b/avm/res/event-grid/topic/README.md @@ -1262,7 +1262,7 @@ Tags of the resource. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/event-hub/namespace/README.md b/avm/res/event-hub/namespace/README.md index d776735da8..679eb8dbc3 100644 --- a/avm/res/event-hub/namespace/README.md +++ b/avm/res/event-hub/namespace/README.md @@ -1824,7 +1824,7 @@ Switch to make the Event Hub Namespace zone redundant. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/insights/private-link-scope/README.md b/avm/res/insights/private-link-scope/README.md index c4366149fd..0bdff8e591 100644 --- a/avm/res/insights/private-link-scope/README.md +++ b/avm/res/insights/private-link-scope/README.md @@ -1372,7 +1372,7 @@ Resource tags. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/key-vault/vault/README.md b/avm/res/key-vault/vault/README.md index c6e2340873..27a7344719 100644 --- a/avm/res/key-vault/vault/README.md +++ b/avm/res/key-vault/vault/README.md @@ -1773,7 +1773,7 @@ Resource tags. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/kubernetes-configuration/extension/README.md b/avm/res/kubernetes-configuration/extension/README.md index da51a32cf5..d97f6041c8 100644 --- a/avm/res/kubernetes-configuration/extension/README.md +++ b/avm/res/kubernetes-configuration/extension/README.md @@ -469,7 +469,7 @@ Version of the extension for this extension, if it is "pinned" to a specific ver ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/machine-learning-services/workspace/README.md b/avm/res/machine-learning-services/workspace/README.md index 86a2be795c..82719f70bd 100644 --- a/avm/res/machine-learning-services/workspace/README.md +++ b/avm/res/machine-learning-services/workspace/README.md @@ -1,7 +1,7 @@ # Machine Learning Services Workspaces `[Microsoft.MachineLearningServices/workspaces]` > ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ -> +> > - Only security and bug fixes are being handled by the AVM core team at present. > - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! @@ -1496,7 +1496,7 @@ Resource tags. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/network/azure-firewall/README.md b/avm/res/network/azure-firewall/README.md index 1a450e250b..a202e20ed1 100644 --- a/avm/res/network/azure-firewall/README.md +++ b/avm/res/network/azure-firewall/README.md @@ -1527,7 +1527,7 @@ Zone numbers e.g. 1,2,3. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/network/bastion-host/README.md b/avm/res/network/bastion-host/README.md index 15f3229fbe..3f82a253e1 100644 --- a/avm/res/network/bastion-host/README.md +++ b/avm/res/network/bastion-host/README.md @@ -887,7 +887,7 @@ Tags of the resource. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/network/nat-gateway/README.md b/avm/res/network/nat-gateway/README.md index b1567ecf30..e9464ccd9b 100644 --- a/avm/res/network/nat-gateway/README.md +++ b/avm/res/network/nat-gateway/README.md @@ -703,7 +703,7 @@ A list of availability zones denoting the zone in which Nat Gateway should be de ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/network/virtual-network-gateway/README.md b/avm/res/network/virtual-network-gateway/README.md index 12f7cc68d9..bfaf37bcf3 100644 --- a/avm/res/network/virtual-network-gateway/README.md +++ b/avm/res/network/virtual-network-gateway/README.md @@ -1668,7 +1668,7 @@ Specifies the VPN type. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/operational-insights/workspace/README.md b/avm/res/operational-insights/workspace/README.md index 683b8c0ec1..89db6a899d 100644 --- a/avm/res/operational-insights/workspace/README.md +++ b/avm/res/operational-insights/workspace/README.md @@ -2217,7 +2217,7 @@ Set to 'true' to use resource or workspace permissions and 'false' (or leave emp ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/purview/account/README.md b/avm/res/purview/account/README.md index 528ce6639c..9d14e21bfb 100644 --- a/avm/res/purview/account/README.md +++ b/avm/res/purview/account/README.md @@ -1,7 +1,7 @@ # Purview Accounts `[Microsoft.Purview/accounts]` > ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ -> +> > - Only security and bug fixes are being handled by the AVM core team at present. > - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! @@ -2628,7 +2628,7 @@ Tags of the resource. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/search/search-service/README.md b/avm/res/search/search-service/README.md index cc2c3d5726..2f113159ab 100644 --- a/avm/res/search/search-service/README.md +++ b/avm/res/search/search-service/README.md @@ -1415,7 +1415,7 @@ Tags to help categorize the resource in the Azure portal. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/service-bus/namespace/README.md b/avm/res/service-bus/namespace/README.md index b599a682dd..8a3c9269d6 100644 --- a/avm/res/service-bus/namespace/README.md +++ b/avm/res/service-bus/namespace/README.md @@ -2905,7 +2905,7 @@ Enabling this property creates a Premium Service Bus Namespace in regions suppor ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/signal-r-service/signal-r/README.md b/avm/res/signal-r-service/signal-r/README.md index fdccaa3df4..4e9d91e25e 100644 --- a/avm/res/signal-r-service/signal-r/README.md +++ b/avm/res/signal-r-service/signal-r/README.md @@ -1,7 +1,7 @@ # SignalR Service SignalR `[Microsoft.SignalRService/signalR]` > ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ -> +> > - Only security and bug fixes are being handled by the AVM core team at present. > - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! @@ -1179,7 +1179,7 @@ Upstream templates to enable. For more information, see https://learn.microsoft. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | 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 c58a1d0a7e..32fc5e052b 100644 --- a/avm/res/signal-r-service/web-pub-sub/README.md +++ b/avm/res/signal-r-service/web-pub-sub/README.md @@ -1,7 +1,7 @@ # SignalR Web PubSub Services `[Microsoft.SignalRService/webPubSub]` > ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ -> +> > - Only security and bug fixes are being handled by the AVM core team at present. > - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! @@ -1125,7 +1125,7 @@ Tags of the resource. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/sql/server/README.md b/avm/res/sql/server/README.md index 67a838766f..57de0cac75 100644 --- a/avm/res/sql/server/README.md +++ b/avm/res/sql/server/README.md @@ -1714,7 +1714,7 @@ The vulnerability assessment configuration. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/storage/storage-account/README.md b/avm/res/storage/storage-account/README.md index 475a9544ee..120deb76dc 100644 --- a/avm/res/storage/storage-account/README.md +++ b/avm/res/storage/storage-account/README.md @@ -3119,7 +3119,7 @@ Tags of the resource. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/synapse/private-link-hub/README.md b/avm/res/synapse/private-link-hub/README.md index 7534fb874e..4299c4f1aa 100644 --- a/avm/res/synapse/private-link-hub/README.md +++ b/avm/res/synapse/private-link-hub/README.md @@ -1,7 +1,7 @@ # Azure Synapse Analytics `[Microsoft.Synapse/privateLinkHubs]` > ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ -> +> > - Only security and bug fixes are being handled by the AVM core team at present. > - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! @@ -826,7 +826,7 @@ Tags of the resource. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/synapse/workspace/README.md b/avm/res/synapse/workspace/README.md index ac0814390f..79a2bd33e4 100644 --- a/avm/res/synapse/workspace/README.md +++ b/avm/res/synapse/workspace/README.md @@ -1,7 +1,7 @@ # Synapse Workspaces `[Microsoft.Synapse/workspaces]` > ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ -> +> > - Only security and bug fixes are being handled by the AVM core team at present. > - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! @@ -1590,7 +1590,7 @@ Git integration settings. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/web/site/README.md b/avm/res/web/site/README.md index 328a2d239d..3411f74e58 100644 --- a/avm/res/web/site/README.md +++ b/avm/res/web/site/README.md @@ -2145,7 +2145,7 @@ Virtual Network Route All enabled. This causes all outbound traffic to have Virt ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/web/site/slot/README.md b/avm/res/web/site/slot/README.md index cc231618ef..6c8923f3a8 100644 --- a/avm/res/web/site/slot/README.md +++ b/avm/res/web/site/slot/README.md @@ -1023,7 +1023,7 @@ Virtual Network Route All enabled. This causes all outbound traffic to have Virt ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/web/static-site/README.md b/avm/res/web/static-site/README.md index 2c5d5d71f5..a0460e02f2 100644 --- a/avm/res/web/static-site/README.md +++ b/avm/res/web/static-site/README.md @@ -1119,7 +1119,7 @@ Template Options for the static site. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/utilities/pipelines/sharedScripts/Set-ModuleReadMe.ps1 b/avm/utilities/pipelines/sharedScripts/Set-ModuleReadMe.ps1 index ebb4cdac4d..5f50885f05 100644 --- a/avm/utilities/pipelines/sharedScripts/Set-ModuleReadMe.ps1 +++ b/avm/utilities/pipelines/sharedScripts/Set-ModuleReadMe.ps1 @@ -625,7 +625,7 @@ function Set-CrossReferencesSection { # Process content $SectionContent = [System.Collections.ArrayList]@( - 'This section gives you an overview of all local-referenced module files (i.e., other CARML 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).', + '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 |', '| :-- | :-- |' @@ -677,13 +677,13 @@ Mandatory. A list of all top-level (i.e. non-nested) parameter names Mandatory. A list of all required top-level (i.e. non-nested) parameter names .EXAMPLE -Add-BicepParameterTypeComment -AllParametersList @('name', 'lock') -RequiredParametersList @('name') -BicepParams "name: 'carml'\nlock: 'CanNotDelete'" +Add-BicepParameterTypeComment -AllParametersList @('name', 'lock') -RequiredParametersList @('name') -BicepParams "name: 'module'\nlock: 'CanNotDelete'" Add type comments to given bicep params string, using one required parameter 'name'. Would return: ' // Required parameters - name: 'carml' + name: 'module' // Non-required parameters lock: { kind: 'CanNotDelete' @@ -757,12 +757,12 @@ Mandatory. The JSON parameters block to process (ideally already without 'value' Mandatory. A list of all required top-level (i.e. non-nested) parameter names .EXAMPLE -Get-OrderedParametersJSON -RequiredParametersList @('name') -ParametersJSON '{ "lock": "CanNotDelete","name": "carml" }' +Get-OrderedParametersJSON -RequiredParametersList @('name') -ParametersJSON '{ "lock": "CanNotDelete","name": "module" }' Order the given JSON object alphabetically. Would result into: @{ - name: 'carml' + name: 'module' lock: { kind: 'CanNotDelete' name: 'myCustomLockName' @@ -815,7 +815,7 @@ Mandatory. The parameter JSON object to process Mandatory. A list of all required top-level (i.e. non-nested) parameter names .EXAMPLE -Build-OrderedJSONObject -RequiredParametersList @('name') -ParametersJSON '{ "lock": { "value": "CanNotDelete" }, "name": { "value": "carml" } }' +Build-OrderedJSONObject -RequiredParametersList @('name') -ParametersJSON '{ "lock": { "value": "CanNotDelete" }, "name": { "value": "module" } }' Build a formatted Parameter-JSON object with one required parameter. Would result into: @@ -825,7 +825,7 @@ Build a formatted Parameter-JSON object with one required parameter. Would resul "parameters": { // Required parameters "name": { - "value": "carml" + "value": "module" }, // Non-required parameters "lock": { @@ -902,13 +902,13 @@ Mandatory. The Bicep parameter block to process Mandatory. The Path of the file containing the param block .EXAMPLE -ConvertTo-FormattedJSONParameterObject -BicepParamBlock "name: 'carml'\nlock: 'CanNotDelete'" -CurrentFilePath 'c:/main.test.bicep' +ConvertTo-FormattedJSONParameterObject -BicepParamBlock "name: 'module'\nlock: 'CanNotDelete'" -CurrentFilePath 'c:/main.test.bicep' -Convert the Bicep string "name: 'carml'\nlock: 'CanNotDelete'" into a parameter JSON object. Would result into: +Convert the Bicep string "name: 'module'\nlock: 'CanNotDelete'" into a parameter JSON object. Would result into: @{ lock = @{ - value = 'carml' + value = 'module' } lock = @{ value = 'CanNotDelete' @@ -1048,13 +1048,13 @@ Mandatory. The parameter JSON object to process. Mandatory. A list of all required top-level (i.e. non-nested) parameter names .EXAMPLE -ConvertTo-FormattedBicep -RequiredParametersList @('name') -JSONParameters @{ lock = @{ value = 'carml' }; lock = @{ value = 'CanNotDelete' } } +ConvertTo-FormattedBicep -RequiredParametersList @('name') -JSONParameters @{ lock = @{ value = 'module' }; lock = @{ value = 'CanNotDelete' } } Convert the given JSONParameters object with one required parameter to a formatted Bicep object. Would result into: ' // Required parameters - name: 'carml' + name: 'module' // Non-required parameters lock: { kind: 'CanNotDelete' From e04bf6a47e117dc6743027bb8738fc681e785f0f Mon Sep 17 00:00:00 2001 From: Clint Grove <30802291+clintgrove@users.noreply.github.com> Date: Wed, 20 Mar 2024 09:40:07 +0000 Subject: [PATCH 45/73] feat: Integration Runtime description added (#1322) ## Description As many Integration Runtimes can be spun up, it is beneficial to have a description of each in order to identify them and help future developers Fixes #1254 Closes #1254 --> ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.data-factory.factory](https://github.com/clintgrove/bicep-registry-modules/actions/workflows/avm.res.data-factory.factory.yml/badge.svg?branch=irdescription)](https://github.com/clintgrove/bicep-registry-modules/actions/workflows/avm.res.data-factory.factory.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [ ] Azure Verified Module updates: - [ ] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [x] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [x] I have run `Set-AVMModule` locally to generate the supporting module files. - [x] My corresponding pipelines / checks run clean and green without any errors or warnings --- .../factory/integration-runtime/README.md | 9 +++++++ .../factory/integration-runtime/main.bicep | 4 +++ .../factory/integration-runtime/main.json | 13 +++++++--- avm/res/data-factory/factory/main.json | 25 ++++++++++++------- .../factory/managed-virtual-network/main.json | 8 +++--- .../managed-private-endpoint/main.json | 4 +-- 6 files changed, 45 insertions(+), 18 deletions(-) diff --git a/avm/res/data-factory/factory/integration-runtime/README.md b/avm/res/data-factory/factory/integration-runtime/README.md index 5fd421712a..910743c3a9 100644 --- a/avm/res/data-factory/factory/integration-runtime/README.md +++ b/avm/res/data-factory/factory/integration-runtime/README.md @@ -36,6 +36,7 @@ This module deploys a Data Factory Managed or Self-Hosted Integration Runtime. | Parameter | Type | Description | | :-- | :-- | :-- | +| [`interagrationRuntimeCustomDescription`](#parameter-interagrationruntimecustomdescription) | string | The description of the Integration Runtime. | | [`managedVirtualNetworkName`](#parameter-managedvirtualnetworkname) | string | The name of the Managed Virtual Network if using type "Managed" . | | [`typeProperties`](#parameter-typeproperties) | object | Integration Runtime type properties. Required if type is "Managed". | @@ -67,6 +68,14 @@ The name of the parent Azure Data Factory. Required if the template is used in a - Required: Yes - Type: string +### Parameter: `interagrationRuntimeCustomDescription` + +The description of the Integration Runtime. + +- Required: No +- Type: string +- Default: `'Managed Integration Runtime created by avm-res-datafactory-factories'` + ### Parameter: `managedVirtualNetworkName` The name of the Managed Virtual Network if using type "Managed" . diff --git a/avm/res/data-factory/factory/integration-runtime/main.bicep b/avm/res/data-factory/factory/integration-runtime/main.bicep index 5b80ef8fce..2c2e252d4e 100644 --- a/avm/res/data-factory/factory/integration-runtime/main.bicep +++ b/avm/res/data-factory/factory/integration-runtime/main.bicep @@ -21,6 +21,9 @@ param managedVirtualNetworkName string = '' @description('Optional. Integration Runtime type properties. Required if type is "Managed".') param typeProperties object = {} +@description('Optional. The description of the Integration Runtime.') +param interagrationRuntimeCustomDescription string = 'Managed Integration Runtime created by avm-res-datafactory-factories' + var managedVirtualNetworkVar = { referenceName: type == 'Managed' ? managedVirtualNetworkName : null type: type == 'Managed' ? 'ManagedVirtualNetworkReference' : null @@ -34,6 +37,7 @@ resource integrationRuntime 'Microsoft.DataFactory/factories/integrationRuntimes name: name parent: dataFactory properties: type == 'Managed' ? { + description: interagrationRuntimeCustomDescription type: type managedVirtualNetwork: managedVirtualNetworkVar typeProperties: typeProperties diff --git a/avm/res/data-factory/factory/integration-runtime/main.json b/avm/res/data-factory/factory/integration-runtime/main.json index 08a41bf9c3..25dade0fb5 100644 --- a/avm/res/data-factory/factory/integration-runtime/main.json +++ b/avm/res/data-factory/factory/integration-runtime/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "7384162383092533956" + "version": "0.26.54.24096", + "templateHash": "5995255380692588407" }, "name": "Data Factory Integration RunTimes", "description": "This module deploys a Data Factory Managed or Self-Hosted Integration Runtime.", @@ -47,6 +47,13 @@ "metadata": { "description": "Optional. Integration Runtime type properties. Required if type is \"Managed\"." } + }, + "interagrationRuntimeCustomDescription": { + "type": "string", + "defaultValue": "Managed Integration Runtime created by avm-res-datafactory-factories", + "metadata": { + "description": "Optional. The description of the Integration Runtime." + } } }, "variables": { @@ -60,7 +67,7 @@ "type": "Microsoft.DataFactory/factories/integrationRuntimes", "apiVersion": "2018-06-01", "name": "[format('{0}/{1}', parameters('dataFactoryName'), parameters('name'))]", - "properties": "[if(equals(parameters('type'), 'Managed'), createObject('type', parameters('type'), 'managedVirtualNetwork', variables('managedVirtualNetworkVar'), 'typeProperties', parameters('typeProperties')), createObject('type', parameters('type')))]" + "properties": "[if(equals(parameters('type'), 'Managed'), createObject('description', parameters('interagrationRuntimeCustomDescription'), 'type', parameters('type'), 'managedVirtualNetwork', variables('managedVirtualNetworkVar'), 'typeProperties', parameters('typeProperties')), createObject('type', parameters('type')))]" } ], "outputs": { diff --git a/avm/res/data-factory/factory/main.json b/avm/res/data-factory/factory/main.json index 3d71e6ca6c..f38a76b6f1 100644 --- a/avm/res/data-factory/factory/main.json +++ b/avm/res/data-factory/factory/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "15512301092613886840" + "version": "0.26.54.24096", + "templateHash": "17591619092727607098" }, "name": "Data Factories", "description": "This module deploys a Data Factory.", @@ -816,8 +816,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "13192908070354977743" + "version": "0.26.54.24096", + "templateHash": "11423521716306055194" }, "name": "Data Factory Managed Virtual Networks", "description": "This module deploys a Data Factory Managed Virtual Network.", @@ -890,8 +890,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "727544206896372572" + "version": "0.26.54.24096", + "templateHash": "15559328970285278624" }, "name": "Data Factory Managed Virtual Network Managed PrivateEndpoints", "description": "This module deploys a Data Factory Managed Virtual Network Managed Private Endpoint.", @@ -1035,8 +1035,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "7384162383092533956" + "version": "0.26.54.24096", + "templateHash": "5995255380692588407" }, "name": "Data Factory Integration RunTimes", "description": "This module deploys a Data Factory Managed or Self-Hosted Integration Runtime.", @@ -1078,6 +1078,13 @@ "metadata": { "description": "Optional. Integration Runtime type properties. Required if type is \"Managed\"." } + }, + "interagrationRuntimeCustomDescription": { + "type": "string", + "defaultValue": "Managed Integration Runtime created by avm-res-datafactory-factories", + "metadata": { + "description": "Optional. The description of the Integration Runtime." + } } }, "variables": { @@ -1091,7 +1098,7 @@ "type": "Microsoft.DataFactory/factories/integrationRuntimes", "apiVersion": "2018-06-01", "name": "[format('{0}/{1}', parameters('dataFactoryName'), parameters('name'))]", - "properties": "[if(equals(parameters('type'), 'Managed'), createObject('type', parameters('type'), 'managedVirtualNetwork', variables('managedVirtualNetworkVar'), 'typeProperties', parameters('typeProperties')), createObject('type', parameters('type')))]" + "properties": "[if(equals(parameters('type'), 'Managed'), createObject('description', parameters('interagrationRuntimeCustomDescription'), 'type', parameters('type'), 'managedVirtualNetwork', variables('managedVirtualNetworkVar'), 'typeProperties', parameters('typeProperties')), createObject('type', parameters('type')))]" } ], "outputs": { diff --git a/avm/res/data-factory/factory/managed-virtual-network/main.json b/avm/res/data-factory/factory/managed-virtual-network/main.json index a7d485a538..e4088f00fc 100644 --- a/avm/res/data-factory/factory/managed-virtual-network/main.json +++ b/avm/res/data-factory/factory/managed-virtual-network/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "13192908070354977743" + "version": "0.26.54.24096", + "templateHash": "11423521716306055194" }, "name": "Data Factory Managed Virtual Networks", "description": "This module deploys a Data Factory Managed Virtual Network.", @@ -78,8 +78,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "727544206896372572" + "version": "0.26.54.24096", + "templateHash": "15559328970285278624" }, "name": "Data Factory Managed Virtual Network Managed PrivateEndpoints", "description": "This module deploys a Data Factory Managed Virtual Network Managed Private Endpoint.", diff --git a/avm/res/data-factory/factory/managed-virtual-network/managed-private-endpoint/main.json b/avm/res/data-factory/factory/managed-virtual-network/managed-private-endpoint/main.json index ad3f95edbc..9ecd792ec3 100644 --- a/avm/res/data-factory/factory/managed-virtual-network/managed-private-endpoint/main.json +++ b/avm/res/data-factory/factory/managed-virtual-network/managed-private-endpoint/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "727544206896372572" + "version": "0.26.54.24096", + "templateHash": "15559328970285278624" }, "name": "Data Factory Managed Virtual Network Managed PrivateEndpoints", "description": "This module deploys a Data Factory Managed Virtual Network Managed Private Endpoint.", From 2126fbd9cc9ffcc15734dc1a4a3733a09fb78242 Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Wed, 20 Mar 2024 17:12:45 +0000 Subject: [PATCH 46/73] feat: Add VM AZ Parameter Test (#1334) ## Description This pull request primarily introduces a new unit test in the `avm/res/compute/virtual-machine/tests/unit/az.tests.ps1` file. The unit test ensures that the Availability Zone parameter in the VM Module does not have a default value set. Key changes include: * [`avm/res/compute/virtual-machine/tests/unit/az.tests.ps1`](diffhunk://#diff-709a50b14d616bcd12c7ca2e17421ba839293f79ba97d0bee05070ba38cadf56R1-R20): Added a new parameter `$repoRootPath` which is optional. Also, added a script to import the `Get-IsParameterRequired.ps1` helper script from the shared scripts directory. * [`avm/res/compute/virtual-machine/tests/unit/az.tests.ps1`](diffhunk://#diff-709a50b14d616bcd12c7ca2e17421ba839293f79ba97d0bee05070ba38cadf56R1-R20): Added a `BeforeAll` block that reads the content of `main.json` into a hashtable. * [`avm/res/compute/virtual-machine/tests/unit/az.tests.ps1`](diffhunk://#diff-709a50b14d616bcd12c7ca2e17421ba839293f79ba97d0bee05070ba38cadf56R1-R20): Introduced a new unit test under the `Describe` block titled 'Availability Zone Tests'. This test checks if the Availability Zone parameter in the VM Module has a default value set. If it does, the test fails. ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.compute.virtual-machine](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.compute.virtual-machine.yml/badge.svg)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.compute.virtual-machine.yml) | > Failure is expected as the module is currently not complaint ## Type of Change - [x] Update to CI Environment or utlities (Non-module effecting changes) - [ ] Azure Verified Module updates: - [ ] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [ ] I have run `Set-AVMModule` locally to generate the supporting module files. - [ ] My corresponding pipelines / checks run clean and green without any errors or warnings --- .github/CODEOWNERS | 2 + .../avm-validateModulePester/action.yml | 1 + .../tests/unit/avm.core.team.tests.ps1 | 40 +++++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 avm/res/compute/virtual-machine/tests/unit/avm.core.team.tests.ps1 diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 335d7842a5..a2e1e73bc0 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -145,3 +145,5 @@ #/avm/ptn/avd-lza/networking/ @Azure/avm-ptn-avd-lza-networking-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/ptn/avd-lza/session-hosts/ @Azure/avm-ptn-avd-lza-sessionhosts-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/ptn/security/security-center/ @Azure/avm-ptn-securitycenter-module-owners-bicep @Azure/avm-core-team-technical-bicep + +*avm.core.team.tests.ps1 @Azure/avm-core-team-technical-bicep diff --git a/.github/actions/templates/avm-validateModulePester/action.yml b/.github/actions/templates/avm-validateModulePester/action.yml index 97e46b8725..d1e6248922 100644 --- a/.github/actions/templates/avm-validateModulePester/action.yml +++ b/.github/actions/templates/avm-validateModulePester/action.yml @@ -72,6 +72,7 @@ runs: Run = @{ Container = New-PesterContainer -Path $testFiles -Data @{ moduleFolderPaths = $moduleFolderPaths + RepoRootPath = $env:GITHUB_WORKSPACE } PassThru = $true } diff --git a/avm/res/compute/virtual-machine/tests/unit/avm.core.team.tests.ps1 b/avm/res/compute/virtual-machine/tests/unit/avm.core.team.tests.ps1 new file mode 100644 index 0000000000..c1e4211675 --- /dev/null +++ b/avm/res/compute/virtual-machine/tests/unit/avm.core.team.tests.ps1 @@ -0,0 +1,40 @@ +<# +.SYNOPSIS +This file contains Pester tests that the AVM Core Team has written for the module. Any additions or changes to these tests will need to be reviewed by the AVM Core Team, this is handled by CODEOWNERS. + +If you wish to add your own Pester tests for you module create a new .tests.ps1 file in the /tests/unit folder of your module. +#> + +param ( + [Parameter(Mandatory = $false)] + [array] $moduleFolderPaths, + + [Parameter(Mandatory = $false)] + [string] $repoRootPath +) + +BeforeAll { + . (Join-Path $RepoRootPath 'avm' 'utilities' 'pipelines' 'sharedScripts' 'helper' 'Get-IsParameterRequired.ps1') + + if ($moduleFolderPaths.Count -gt 1) { + $topLevelModuleTemplatePath = $moduleFolderPaths | Sort-Object | Select-Object -First 1 + } + else { + $topLevelModuleTemplatePath = $moduleFolderPaths + } + + $moduleJsonContentHashtable = Get-Content -Path (Join-Path $topLevelModuleTemplatePath 'main.json') | ConvertFrom-Json -AsHashtable +} + +Describe 'AVM Core Team Module Specific Tests' { + + Context 'WAF - Reliability Pillar - Parameter Tests' { + + It 'VM Module Availability Zone Parameter Should Not Have A Default Value Set' { + $isRequired = Get-IsParameterRequired -TemplateFileContent $moduleJsonContentHashtable -Parameter $moduleJsonContentHashtable.parameters.availabilityZone + $isRequired | Should -Be $true + } + + } + +} From ed897c0c160de3402e9b59b1895dcf924ec98429 Mon Sep 17 00:00:00 2001 From: Clint Grove <30802291+clintgrove@users.noreply.github.com> Date: Wed, 20 Mar 2024 17:17:26 +0000 Subject: [PATCH 47/73] fix: 1341 IR description passthrough (#1343) ## Description The IR description was left out of the main parent bicep file Fixes #1341 Closes #1341 --> ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.data-factory.factory](https://github.com/clintgrove/bicep-registry-modules/actions/workflows/avm.res.data-factory.factory.yml/badge.svg?branch=irdescpassthrough)](https://github.com/clintgrove/bicep-registry-modules/actions/workflows/avm.res.data-factory.factory.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [x] Azure Verified Module updates: - [ ] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [x] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [x] I have run `Set-AVMModule` locally to generate the supporting module files. - [x] My corresponding pipelines / checks run clean and green without any errors or warnings Co-authored-by: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> --- avm/res/data-factory/factory/main.bicep | 1 + avm/res/data-factory/factory/main.json | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/avm/res/data-factory/factory/main.bicep b/avm/res/data-factory/factory/main.bicep index 9f692af3d6..02a736accc 100644 --- a/avm/res/data-factory/factory/main.bicep +++ b/avm/res/data-factory/factory/main.bicep @@ -172,6 +172,7 @@ module dataFactory_integrationRuntimes 'integration-runtime/main.bicep' = [for ( dataFactoryName: dataFactory.name name: integrationRuntime.name type: integrationRuntime.type + interagrationRuntimeCustomDescription: integrationRuntime.?interagrationRuntimeCustomDescription ?? 'Managed Integration Runtime created by avm-res-datafactory-factories' managedVirtualNetworkName: contains(integrationRuntime, 'managedVirtualNetworkName') ? integrationRuntime.managedVirtualNetworkName : '' typeProperties: contains(integrationRuntime, 'typeProperties') ? integrationRuntime.typeProperties : {} } diff --git a/avm/res/data-factory/factory/main.json b/avm/res/data-factory/factory/main.json index f38a76b6f1..309d4053b9 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.26.54.24096", - "templateHash": "17591619092727607098" + "templateHash": "18305717161046402755" }, "name": "Data Factories", "description": "This module deploys a Data Factory.", @@ -1026,6 +1026,9 @@ "type": { "value": "[parameters('integrationRuntimes')[copyIndex()].type]" }, + "interagrationRuntimeCustomDescription": { + "value": "[coalesce(tryGet(parameters('integrationRuntimes')[copyIndex()], 'interagrationRuntimeCustomDescription'), 'Managed Integration Runtime created by avm-res-datafactory-factories')]" + }, "managedVirtualNetworkName": "[if(contains(parameters('integrationRuntimes')[copyIndex()], 'managedVirtualNetworkName'), createObject('value', parameters('integrationRuntimes')[copyIndex()].managedVirtualNetworkName), createObject('value', ''))]", "typeProperties": "[if(contains(parameters('integrationRuntimes')[copyIndex()], 'typeProperties'), createObject('value', parameters('integrationRuntimes')[copyIndex()].typeProperties), createObject('value', createObject()))]" }, From 42baba913b3954c9d4586341ef6295ed1dca1fdf Mon Sep 17 00:00:00 2001 From: Buddy <38195643+tsc-buddy@users.noreply.github.com> Date: Thu, 21 Mar 2024 11:46:13 +1300 Subject: [PATCH 48/73] feat: Sites - Linux support (#1317) ## Description Added support for Linux based Web sites. Also some minor test changes to accommodate the WAF reliability tests in CI. Closes #1105 ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.web.site](https://github.com/tsc-buddy/bicep-registry-modules/actions/workflows/avm.res.web.site.yml/badge.svg?branch=feat%2Flinux-support)](https://github.com/tsc-buddy/bicep-registry-modules/actions/workflows/avm.res.web.site.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [ ] Azure Verified Module updates: - [ ] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [x] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [x] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [x] I have run `Set-AVMModule` locally to generate the supporting module files. - [x] My corresponding pipelines / checks run clean and green without any errors or warnings --------- Co-authored-by: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> --- avm/res/web/site/README.md | 518 ++++++++++++++++++ .../main.json | 4 +- .../web/site/config--appsettings/README.md | 1 + .../web/site/config--appsettings/main.bicep | 1 + .../web/site/config--appsettings/main.json | 5 +- .../web/site/config--authsettingsv2/README.md | 1 + .../site/config--authsettingsv2/main.bicep | 1 + .../web/site/config--authsettingsv2/main.json | 5 +- .../relay/main.json | 4 +- avm/res/web/site/main.bicep | 1 + avm/res/web/site/main.json | 46 +- avm/res/web/site/slot/README.md | 1 + .../main.json | 4 +- .../site/slot/config--appsettings/README.md | 1 + .../site/slot/config--appsettings/main.bicep | 1 + .../site/slot/config--appsettings/main.json | 5 +- .../slot/config--authsettingsv2/README.md | 1 + .../slot/config--authsettingsv2/main.bicep | 1 + .../slot/config--authsettingsv2/main.json | 5 +- .../relay/main.json | 4 +- avm/res/web/site/slot/main.bicep | 1 + avm/res/web/site/slot/main.json | 23 +- .../tests/e2e/waf-aligned/main.test.bicep | 1 + .../tests/e2e/webApp.defaults/main.test.bicep | 5 + .../webAppLinux.defaults/dependencies.bicep | 23 + .../e2e/webAppLinux.defaults/main.test.bicep | 60 ++ .../e2e/webAppLinux.max/dependencies.bicep | 139 +++++ .../tests/e2e/webAppLinux.max/main.test.bicep | 258 +++++++++ 28 files changed, 1074 insertions(+), 46 deletions(-) create mode 100644 avm/res/web/site/tests/e2e/webAppLinux.defaults/dependencies.bicep create mode 100644 avm/res/web/site/tests/e2e/webAppLinux.defaults/main.test.bicep create mode 100644 avm/res/web/site/tests/e2e/webAppLinux.max/dependencies.bicep create mode 100644 avm/res/web/site/tests/e2e/webAppLinux.max/main.test.bicep diff --git a/avm/res/web/site/README.md b/avm/res/web/site/README.md index 3411f74e58..65ab42e075 100644 --- a/avm/res/web/site/README.md +++ b/avm/res/web/site/README.md @@ -43,6 +43,8 @@ The following section provides usage examples for the module, which were used to - [WAF-aligned](#example-3-waf-aligned) - [Web App, using only defaults](#example-4-web-app-using-only-defaults) - [Web App, using large parameter set](#example-5-web-app-using-large-parameter-set) +- [Web App, using only defaults](#example-6-web-app-using-only-defaults) +- [Web App, using large parameter set](#example-7-web-app-using-large-parameter-set) ### Example 1: _Function App, using only defaults_ @@ -538,6 +540,7 @@ module site 'br/public:avm/res/web/site:' = { scmSiteAlsoStopped: true siteConfig: { alwaysOn: true + healthCheckPath: '/healthz' metadata: [ { name: 'CURRENT_STACK' @@ -612,6 +615,7 @@ module site 'br/public:avm/res/web/site:' = { "siteConfig": { "value": { "alwaysOn": true, + "healthCheckPath": "/healthz", "metadata": [ { "name": "CURRENT_STACK", @@ -655,7 +659,12 @@ module site 'br/public:avm/res/web/site:' = { serverFarmResourceId: '' // Non-required parameters location: '' + siteConfig: { + alwaysOn: true + healthCheckPath: '/healthz' + } } + } ``` @@ -684,6 +693,12 @@ module site 'br/public:avm/res/web/site:' = { // Non-required parameters "location": { "value": "" + }, + "siteConfig": { + "value": { + "alwaysOn": true, + "healthCheckPath": "/healthz" + } } } } @@ -1138,6 +1153,508 @@ module site 'br/public:avm/res/web/site:' = {

+### Example 6: _Web App, using only defaults_ + +This instance deploys the module as a Linux Web App with the minimum set of required parameters. + + +

+ +via Bicep module + +```bicep +module site 'br/public:avm/res/web/site:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-wswalmin' + params: { + // Required parameters + kind: 'app,linux' + name: 'wswalmin001' + serverFarmResourceId: '' + // Non-required parameters + location: '' + } +} +``` + +
+

+ +

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

+ +### Example 7: _Web App, using large parameter set_ + +This instance deploys the module asa Linux Web App with most of its features enabled. + + +

+ +via Bicep module + +```bicep +module site 'br/public:avm/res/web/site:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-wswalmax' + params: { + // Required parameters + kind: 'app,linux' + name: 'wswalmax001' + serverFarmResourceId: '' + // Non-required parameters + basicPublishingCredentialsPolicies: [ + { + allow: false + name: 'ftp' + } + { + allow: false + name: 'scm' + } + ] + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + httpsOnly: true + hybridConnectionRelays: [ + { + resourceId: '' + sendKeyName: 'defaultSender' + } + ] + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + '' + ] + } + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + '' + ] + subnetResourceId: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + { + privateDnsZoneResourceIds: [ + '' + ] + subnetResourceId: '' + } + ] + publicNetworkAccess: 'Disabled' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + scmSiteAlsoStopped: true + siteConfig: { + alwaysOn: true + metadata: [ + { + name: 'CURRENT_STACK' + value: 'dotnetcore' + } + ] + } + slots: [ + { + basicPublishingCredentialsPolicies: [ + { + allow: false + name: 'ftp' + } + { + allow: false + name: 'scm' + } + ] + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + hybridConnectionRelays: [ + { + resourceId: '' + sendKeyName: 'defaultSender' + } + ] + name: 'slot1' + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + '' + ] + service: 'sites-slot1' + subnetResourceId: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + ] + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + siteConfig: { + alwaysOn: true + metadata: [ + { + name: 'CURRENT_STACK' + value: 'dotnetcore' + } + ] + } + storageAccountResourceId: '' + storageAccountUseIdentityAuthentication: true + } + { + basicPublishingCredentialsPolicies: [ + { + name: 'ftp' + } + { + name: 'scm' + } + ] + name: 'slot2' + storageAccountResourceId: '' + storageAccountUseIdentityAuthentication: true + } + ] + storageAccountResourceId: '' + storageAccountUseIdentityAuthentication: true + vnetContentShareEnabled: true + vnetImagePullEnabled: true + vnetRouteAllEnabled: true + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "kind": { + "value": "app,linux" + }, + "name": { + "value": "wswalmax001" + }, + "serverFarmResourceId": { + "value": "" + }, + // Non-required parameters + "basicPublishingCredentialsPolicies": { + "value": [ + { + "allow": false, + "name": "ftp" + }, + { + "allow": false, + "name": "scm" + } + ] + }, + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "httpsOnly": { + "value": true + }, + "hybridConnectionRelays": { + "value": [ + { + "resourceId": "", + "sendKeyName": "defaultSender" + } + ] + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "managedIdentities": { + "value": { + "systemAssigned": true, + "userAssignedResourceIds": [ + "" + ] + } + }, + "privateEndpoints": { + "value": [ + { + "privateDnsZoneResourceIds": [ + "" + ], + "subnetResourceId": "", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + { + "privateDnsZoneResourceIds": [ + "" + ], + "subnetResourceId": "" + } + ] + }, + "publicNetworkAccess": { + "value": "Disabled" + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "scmSiteAlsoStopped": { + "value": true + }, + "siteConfig": { + "value": { + "alwaysOn": true, + "metadata": [ + { + "name": "CURRENT_STACK", + "value": "dotnetcore" + } + ] + } + }, + "slots": { + "value": [ + { + "basicPublishingCredentialsPolicies": [ + { + "allow": false, + "name": "ftp" + }, + { + "allow": false, + "name": "scm" + } + ], + "diagnosticSettings": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ], + "hybridConnectionRelays": [ + { + "resourceId": "", + "sendKeyName": "defaultSender" + } + ], + "name": "slot1", + "privateEndpoints": [ + { + "privateDnsZoneResourceIds": [ + "" + ], + "service": "sites-slot1", + "subnetResourceId": "", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + ], + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ], + "siteConfig": { + "alwaysOn": true, + "metadata": [ + { + "name": "CURRENT_STACK", + "value": "dotnetcore" + } + ] + }, + "storageAccountResourceId": "", + "storageAccountUseIdentityAuthentication": true + }, + { + "basicPublishingCredentialsPolicies": [ + { + "name": "ftp" + }, + { + "name": "scm" + } + ], + "name": "slot2", + "storageAccountResourceId": "", + "storageAccountUseIdentityAuthentication": true + } + ] + }, + "storageAccountResourceId": { + "value": "" + }, + "storageAccountUseIdentityAuthentication": { + "value": true + }, + "vnetContentShareEnabled": { + "value": true + }, + "vnetImagePullEnabled": { + "value": true + }, + "vnetRouteAllEnabled": { + "value": true + } + } +} +``` + +
+

+ ## Parameters @@ -1203,6 +1720,7 @@ Type of site to deploy. ```Bicep [ 'app' + 'app,linux' 'functionapp' 'functionapp,linux' 'functionapp,workflowapp' 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 6f99540b9b..cc6e4e5abb 100644 --- a/avm/res/web/site/basic-publishing-credentials-policy/main.json +++ b/avm/res/web/site/basic-publishing-credentials-policy/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2268330248918966432" + "version": "0.26.54.24096", + "templateHash": "12379291046700283915" }, "name": "Web Site Basic Publishing Credentials Policies", "description": "This module deploys a Web Site Basic Publishing Credentials Policy.", diff --git a/avm/res/web/site/config--appsettings/README.md b/avm/res/web/site/config--appsettings/README.md index 0087203af5..524af793b5 100644 --- a/avm/res/web/site/config--appsettings/README.md +++ b/avm/res/web/site/config--appsettings/README.md @@ -50,6 +50,7 @@ Type of site to deploy. ```Bicep [ 'app' + 'app,linux' 'functionapp' 'functionapp,linux' 'functionapp,workflowapp' diff --git a/avm/res/web/site/config--appsettings/main.bicep b/avm/res/web/site/config--appsettings/main.bicep index 7957736263..573c274a95 100644 --- a/avm/res/web/site/config--appsettings/main.bicep +++ b/avm/res/web/site/config--appsettings/main.bicep @@ -11,6 +11,7 @@ param appName string 'functionapp,linux' // function app linux os 'functionapp,workflowapp' // logic app workflow 'functionapp,workflowapp,linux' // logic app docker container + 'app,linux' // linux web app 'app' // normal web app ]) param kind string diff --git a/avm/res/web/site/config--appsettings/main.json b/avm/res/web/site/config--appsettings/main.json index 67706c0b50..aa1a357e49 100644 --- a/avm/res/web/site/config--appsettings/main.json +++ b/avm/res/web/site/config--appsettings/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "1933221834367063613" + "version": "0.26.54.24096", + "templateHash": "18064037455551234601" }, "name": "Site App Settings", "description": "This module deploys a Site App Setting.", @@ -26,6 +26,7 @@ "functionapp,linux", "functionapp,workflowapp", "functionapp,workflowapp,linux", + "app,linux", "app" ], "metadata": { diff --git a/avm/res/web/site/config--authsettingsv2/README.md b/avm/res/web/site/config--authsettingsv2/README.md index 90908d2aaa..81d813e62f 100644 --- a/avm/res/web/site/config--authsettingsv2/README.md +++ b/avm/res/web/site/config--authsettingsv2/README.md @@ -48,6 +48,7 @@ Type of site to deploy. ```Bicep [ 'app' + 'app,linux' 'functionapp' 'functionapp,linux' 'functionapp,workflowapp' diff --git a/avm/res/web/site/config--authsettingsv2/main.bicep b/avm/res/web/site/config--authsettingsv2/main.bicep index 0df3694c1c..69bbdecf57 100644 --- a/avm/res/web/site/config--authsettingsv2/main.bicep +++ b/avm/res/web/site/config--authsettingsv2/main.bicep @@ -11,6 +11,7 @@ param appName string 'functionapp,linux' // function app linux os 'functionapp,workflowapp' // logic app workflow 'functionapp,workflowapp,linux' // logic app docker container + 'app,linux' // linux web app 'app' // normal web app ]) param kind string diff --git a/avm/res/web/site/config--authsettingsv2/main.json b/avm/res/web/site/config--authsettingsv2/main.json index 7a5d89405b..4a56803f1a 100644 --- a/avm/res/web/site/config--authsettingsv2/main.json +++ b/avm/res/web/site/config--authsettingsv2/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "9745043167341352785" + "version": "0.26.54.24096", + "templateHash": "9660352953607316036" }, "name": "Site Auth Settings V2 Config", "description": "This module deploys a Site Auth Settings V2 Configuration.", @@ -25,6 +25,7 @@ "functionapp,linux", "functionapp,workflowapp", "functionapp,workflowapp,linux", + "app,linux", "app" ], "metadata": { 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 127923ade5..9b76669f1b 100644 --- a/avm/res/web/site/hybrid-connection-namespace/relay/main.json +++ b/avm/res/web/site/hybrid-connection-namespace/relay/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "15358142338977814861" + "version": "0.26.54.24096", + "templateHash": "12607693486765150465" }, "name": "Web/Function Apps Hybrid Connection Relay", "description": "This module deploys a Site Hybrid Connection Namespace Relay.", diff --git a/avm/res/web/site/main.bicep b/avm/res/web/site/main.bicep index 8de8ff1d99..a4a63bc236 100644 --- a/avm/res/web/site/main.bicep +++ b/avm/res/web/site/main.bicep @@ -14,6 +14,7 @@ param location string = resourceGroup().location 'functionapp,linux' // function app linux os 'functionapp,workflowapp' // logic app workflow 'functionapp,workflowapp,linux' // logic app docker container + 'app,linux' // linux web app 'app' // normal web app ]) param kind string diff --git a/avm/res/web/site/main.json b/avm/res/web/site/main.json index dc3cf78d44..c536503a67 100644 --- a/avm/res/web/site/main.json +++ b/avm/res/web/site/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "13529659123294184484" + "version": "0.26.54.24096", + "templateHash": "6312828584864471342" }, "name": "Web/Function Apps", "description": "This module deploys a Web or Function App.", @@ -452,6 +452,7 @@ "functionapp,linux", "functionapp,workflowapp", "functionapp,workflowapp,linux", + "app,linux", "app" ], "metadata": { @@ -926,8 +927,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "1933221834367063613" + "version": "0.26.54.24096", + "templateHash": "18064037455551234601" }, "name": "Site App Settings", "description": "This module deploys a Site App Setting.", @@ -947,6 +948,7 @@ "functionapp,linux", "functionapp,workflowapp", "functionapp,workflowapp,linux", + "app,linux", "app" ], "metadata": { @@ -1076,8 +1078,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "9745043167341352785" + "version": "0.26.54.24096", + "templateHash": "9660352953607316036" }, "name": "Site Auth Settings V2 Config", "description": "This module deploys a Site Auth Settings V2 Configuration.", @@ -1097,6 +1099,7 @@ "functionapp,linux", "functionapp,workflowapp", "functionapp,workflowapp,linux", + "app,linux", "app" ], "metadata": { @@ -1295,8 +1298,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11139469624723604210" + "version": "0.26.54.24096", + "templateHash": "12157473410186645235" }, "name": "Web/Function App Deployment Slots", "description": "This module deploys a Web or Function App Deployment Slot.", @@ -1748,6 +1751,7 @@ "functionapp,linux", "functionapp,workflowapp", "functionapp,workflowapp,linux", + "app,linux", "app" ], "metadata": { @@ -2200,8 +2204,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "10996922119937137063" + "version": "0.26.54.24096", + "templateHash": "12764984503745572183" }, "name": "Site Slot App Settings", "description": "This module deploys a Site Slot App Setting.", @@ -2227,6 +2231,7 @@ "functionapp,linux", "functionapp,workflowapp", "functionapp,workflowapp,linux", + "app,linux", "app" ], "metadata": { @@ -2369,8 +2374,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17486786144236938726" + "version": "0.26.54.24096", + "templateHash": "1333776366661137381" }, "name": "Site Slot Auth Settings V2 Config", "description": "This module deploys a Site Auth Settings V2 Configuration.", @@ -2396,6 +2401,7 @@ "functionapp,linux", "functionapp,workflowapp", "functionapp,workflowapp,linux", + "app,linux", "app" ], "metadata": { @@ -2484,8 +2490,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14855550867941906241" + "version": "0.26.54.24096", + "templateHash": "2236066853450471067" }, "name": "Web Site Slot Basic Publishing Credentials Policies", "description": "This module deploys a Web Site Slot Basic Publishing Credentials Policy.", @@ -2610,8 +2616,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17251933783218724711" + "version": "0.26.54.24096", + "templateHash": "1058820827217282473" }, "name": "Web/Function Apps Slot Hybrid Connection Relay", "description": "This module deploys a Site Slot Hybrid Connection Namespace Relay.", @@ -3430,8 +3436,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2268330248918966432" + "version": "0.26.54.24096", + "templateHash": "12379291046700283915" }, "name": "Web Site Basic Publishing Credentials Policies", "description": "This module deploys a Web Site Basic Publishing Credentials Policy.", @@ -3546,8 +3552,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "15358142338977814861" + "version": "0.26.54.24096", + "templateHash": "12607693486765150465" }, "name": "Web/Function Apps Hybrid Connection Relay", "description": "This module deploys a Site Hybrid Connection Namespace Relay.", diff --git a/avm/res/web/site/slot/README.md b/avm/res/web/site/slot/README.md index 6c8923f3a8..0ee42e70e8 100644 --- a/avm/res/web/site/slot/README.md +++ b/avm/res/web/site/slot/README.md @@ -93,6 +93,7 @@ Type of slot to deploy. ```Bicep [ 'app' + 'app,linux' 'functionapp' 'functionapp,linux' 'functionapp,workflowapp' 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 7f350ba33a..5edba81498 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 @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14855550867941906241" + "version": "0.26.54.24096", + "templateHash": "2236066853450471067" }, "name": "Web Site Slot Basic Publishing Credentials Policies", "description": "This module deploys a Web Site Slot Basic Publishing Credentials Policy.", diff --git a/avm/res/web/site/slot/config--appsettings/README.md b/avm/res/web/site/slot/config--appsettings/README.md index 77f530a7b4..fae2e97acb 100644 --- a/avm/res/web/site/slot/config--appsettings/README.md +++ b/avm/res/web/site/slot/config--appsettings/README.md @@ -51,6 +51,7 @@ Type of slot to deploy. ```Bicep [ 'app' + 'app,linux' 'functionapp' 'functionapp,linux' 'functionapp,workflowapp' diff --git a/avm/res/web/site/slot/config--appsettings/main.bicep b/avm/res/web/site/slot/config--appsettings/main.bicep index 3280ade04d..6572451c58 100644 --- a/avm/res/web/site/slot/config--appsettings/main.bicep +++ b/avm/res/web/site/slot/config--appsettings/main.bicep @@ -14,6 +14,7 @@ param appName string 'functionapp,linux' // function app linux os 'functionapp,workflowapp' // logic app workflow 'functionapp,workflowapp,linux' // logic app docker container + 'app,linux' // linux web app 'app' // normal web app ]) param kind string diff --git a/avm/res/web/site/slot/config--appsettings/main.json b/avm/res/web/site/slot/config--appsettings/main.json index 4c6ed30b38..6f64bbb346 100644 --- a/avm/res/web/site/slot/config--appsettings/main.json +++ b/avm/res/web/site/slot/config--appsettings/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "10996922119937137063" + "version": "0.26.54.24096", + "templateHash": "12764984503745572183" }, "name": "Site Slot App Settings", "description": "This module deploys a Site Slot App Setting.", @@ -32,6 +32,7 @@ "functionapp,linux", "functionapp,workflowapp", "functionapp,workflowapp,linux", + "app,linux", "app" ], "metadata": { diff --git a/avm/res/web/site/slot/config--authsettingsv2/README.md b/avm/res/web/site/slot/config--authsettingsv2/README.md index 25457497c1..95c40357ab 100644 --- a/avm/res/web/site/slot/config--authsettingsv2/README.md +++ b/avm/res/web/site/slot/config--authsettingsv2/README.md @@ -49,6 +49,7 @@ Type of slot to deploy. ```Bicep [ 'app' + 'app,linux' 'functionapp' 'functionapp,linux' 'functionapp,workflowapp' diff --git a/avm/res/web/site/slot/config--authsettingsv2/main.bicep b/avm/res/web/site/slot/config--authsettingsv2/main.bicep index 754904b2ee..786abfa9a9 100644 --- a/avm/res/web/site/slot/config--authsettingsv2/main.bicep +++ b/avm/res/web/site/slot/config--authsettingsv2/main.bicep @@ -14,6 +14,7 @@ param slotName string 'functionapp,linux' // function app linux os 'functionapp,workflowapp' // logic app workflow 'functionapp,workflowapp,linux' // logic app docker container + 'app,linux' // linux web app 'app' // normal web app ]) param kind string diff --git a/avm/res/web/site/slot/config--authsettingsv2/main.json b/avm/res/web/site/slot/config--authsettingsv2/main.json index 95aba0cbc2..e066ea03ac 100644 --- a/avm/res/web/site/slot/config--authsettingsv2/main.json +++ b/avm/res/web/site/slot/config--authsettingsv2/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17486786144236938726" + "version": "0.26.54.24096", + "templateHash": "1333776366661137381" }, "name": "Site Slot Auth Settings V2 Config", "description": "This module deploys a Site Auth Settings V2 Configuration.", @@ -31,6 +31,7 @@ "functionapp,linux", "functionapp,workflowapp", "functionapp,workflowapp,linux", + "app,linux", "app" ], "metadata": { 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 814d89b0f7..34a8005abb 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 @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17251933783218724711" + "version": "0.26.54.24096", + "templateHash": "1058820827217282473" }, "name": "Web/Function Apps Slot Hybrid Connection Relay", "description": "This module deploys a Site Slot Hybrid Connection Namespace Relay.", diff --git a/avm/res/web/site/slot/main.bicep b/avm/res/web/site/slot/main.bicep index 1ba45eb733..b5b5cf1354 100644 --- a/avm/res/web/site/slot/main.bicep +++ b/avm/res/web/site/slot/main.bicep @@ -17,6 +17,7 @@ param location string = resourceGroup().location 'functionapp,linux' // function app linux os 'functionapp,workflowapp' // logic app workflow 'functionapp,workflowapp,linux' // logic app docker container + 'app,linux' // linux web app 'app' // normal web app ]) param kind string diff --git a/avm/res/web/site/slot/main.json b/avm/res/web/site/slot/main.json index 811f9db83c..959db7cbac 100644 --- a/avm/res/web/site/slot/main.json +++ b/avm/res/web/site/slot/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11139469624723604210" + "version": "0.26.54.24096", + "templateHash": "12157473410186645235" }, "name": "Web/Function App Deployment Slots", "description": "This module deploys a Web or Function App Deployment Slot.", @@ -458,6 +458,7 @@ "functionapp,linux", "functionapp,workflowapp", "functionapp,workflowapp,linux", + "app,linux", "app" ], "metadata": { @@ -910,8 +911,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "10996922119937137063" + "version": "0.26.54.24096", + "templateHash": "12764984503745572183" }, "name": "Site Slot App Settings", "description": "This module deploys a Site Slot App Setting.", @@ -937,6 +938,7 @@ "functionapp,linux", "functionapp,workflowapp", "functionapp,workflowapp,linux", + "app,linux", "app" ], "metadata": { @@ -1079,8 +1081,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17486786144236938726" + "version": "0.26.54.24096", + "templateHash": "1333776366661137381" }, "name": "Site Slot Auth Settings V2 Config", "description": "This module deploys a Site Auth Settings V2 Configuration.", @@ -1106,6 +1108,7 @@ "functionapp,linux", "functionapp,workflowapp", "functionapp,workflowapp,linux", + "app,linux", "app" ], "metadata": { @@ -1194,8 +1197,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14855550867941906241" + "version": "0.26.54.24096", + "templateHash": "2236066853450471067" }, "name": "Web Site Slot Basic Publishing Credentials Policies", "description": "This module deploys a Web Site Slot Basic Publishing Credentials Policy.", @@ -1320,8 +1323,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17251933783218724711" + "version": "0.26.54.24096", + "templateHash": "1058820827217282473" }, "name": "Web/Function Apps Slot Hybrid Connection Relay", "description": "This module deploys a Site Slot Hybrid Connection Namespace Relay.", diff --git a/avm/res/web/site/tests/e2e/waf-aligned/main.test.bicep b/avm/res/web/site/tests/e2e/waf-aligned/main.test.bicep index 3a0c5c9f24..118c87cf79 100644 --- a/avm/res/web/site/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/web/site/tests/e2e/waf-aligned/main.test.bicep @@ -76,6 +76,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ] httpsOnly: true siteConfig: { + healthCheckPath: '/healthz' alwaysOn: true metadata: [ { diff --git a/avm/res/web/site/tests/e2e/webApp.defaults/main.test.bicep b/avm/res/web/site/tests/e2e/webApp.defaults/main.test.bicep index 327bfd6495..baecb8fbaf 100644 --- a/avm/res/web/site/tests/e2e/webApp.defaults/main.test.bicep +++ b/avm/res/web/site/tests/e2e/webApp.defaults/main.test.bicep @@ -53,7 +53,12 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' location: resourceLocation kind: 'app' serverFarmResourceId: nestedDependencies.outputs.serverFarmResourceId + siteConfig: { + healthCheckPath: '/healthz' + alwaysOn: true + } } + dependsOn: [ nestedDependencies ] diff --git a/avm/res/web/site/tests/e2e/webAppLinux.defaults/dependencies.bicep b/avm/res/web/site/tests/e2e/webAppLinux.defaults/dependencies.bicep new file mode 100644 index 0000000000..cc8e14c136 --- /dev/null +++ b/avm/res/web/site/tests/e2e/webAppLinux.defaults/dependencies.bicep @@ -0,0 +1,23 @@ +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +@description('Required. The name of the Server Farm to create.') +param serverFarmName string + +resource serverFarm 'Microsoft.Web/serverfarms@2022-03-01' = { + name: serverFarmName + location: location + sku: { + name: 'S1' + tier: 'Standard' + size: 'S1' + family: 'S' + capacity: 1 + } + properties: { + reserved: true + } +} + +@description('The resource ID of the created Server Farm.') +output serverFarmResourceId string = serverFarm.id diff --git a/avm/res/web/site/tests/e2e/webAppLinux.defaults/main.test.bicep b/avm/res/web/site/tests/e2e/webAppLinux.defaults/main.test.bicep new file mode 100644 index 0000000000..61de2c7c89 --- /dev/null +++ b/avm/res/web/site/tests/e2e/webAppLinux.defaults/main.test.bicep @@ -0,0 +1,60 @@ +targetScope = 'subscription' + +metadata name = 'Web App, using only defaults' +metadata description = 'This instance deploys the module as a Linux Web App 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}-web.sites-${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 = 'wswalmin' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + serverFarmName: 'dep-${namePrefix}-sf-${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 + kind: 'app,linux' + serverFarmResourceId: nestedDependencies.outputs.serverFarmResourceId + } + dependsOn: [ + nestedDependencies + ] +}] diff --git a/avm/res/web/site/tests/e2e/webAppLinux.max/dependencies.bicep b/avm/res/web/site/tests/e2e/webAppLinux.max/dependencies.bicep new file mode 100644 index 0000000000..98bebf66cd --- /dev/null +++ b/avm/res/web/site/tests/e2e/webAppLinux.max/dependencies.bicep @@ -0,0 +1,139 @@ +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +@description('Required. The name of the Server Farm to create.') +param serverFarmName string + +@description('Required. The name of the Storage Account to create.') +param storageAccountName string + +@description('Required. The name of the Relay Namespace to create.') +param relayNamespaceName string + +@description('Required. The name of the Hybrid Connection to create.') +param hybridConnectionName string + +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) + } + } + ] + } +} + +resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { + name: 'privatelink.azurewebsites.net' + location: 'global' + + resource virtualNetworkLinks 'virtualNetworkLinks@2020-06-01' = { + name: '${virtualNetwork.name}-vnetlink' + location: 'global' + properties: { + virtualNetwork: { + id: virtualNetwork.id + } + registrationEnabled: false + } + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource serverFarm 'Microsoft.Web/serverfarms@2022-03-01' = { + name: serverFarmName + location: location + sku: { + name: 'S1' + tier: 'Standard' + size: 'S1' + family: 'S' + capacity: 1 + } + properties: { + reserved: true + } +} + +resource relayNamespace 'Microsoft.Relay/namespaces@2021-11-01' = { + name: relayNamespaceName + location: location + sku: { + name: 'Standard' + } + properties: {} +} + +resource hybridConnection 'Microsoft.Relay/namespaces/hybridConnections@2021-11-01' = { + name: hybridConnectionName + parent: relayNamespace + properties: { + requiresClientAuthorization: true + userMetadata: '[{"key":"endpoint","value":"db-server.constoso.com:1433"}]' + } +} + +resource authorizationRule 'Microsoft.Relay/namespaces/hybridConnections/authorizationRules@2021-11-01' = { + name: 'defaultSender' + parent: hybridConnection + properties: { + rights: [ + 'Send' + ] + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-09-01' = { + name: storageAccountName + location: location + sku: { + name: 'Standard_LRS' + } + kind: 'StorageV2' + properties: { + allowSharedKeyAccess: false + } +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].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 + +@description('The resource ID of the created Server Farm.') +output serverFarmResourceId string = serverFarm.id + +@description('The resource ID of the created Private DNS Zone.') +output privateDNSZoneResourceId string = privateDNSZone.id + +@description('The resource ID of the created Hybrid Connection.') +output hybridConnectionResourceId string = hybridConnection.id + +@description('The resource ID of the created Storage Account.') +output storageAccountResourceId string = storageAccount.id diff --git a/avm/res/web/site/tests/e2e/webAppLinux.max/main.test.bicep b/avm/res/web/site/tests/e2e/webAppLinux.max/main.test.bicep new file mode 100644 index 0000000000..41754c557b --- /dev/null +++ b/avm/res/web/site/tests/e2e/webAppLinux.max/main.test.bicep @@ -0,0 +1,258 @@ +targetScope = 'subscription' + +metadata name = 'Web App, using large parameter set' +metadata description = 'This instance deploys the module asa Linux Web App 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}-web.sites-${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 = 'wswalmax' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + serverFarmName: 'dep-${namePrefix}-sf-${serviceShort}' + relayNamespaceName: 'dep-${namePrefix}-ns-${serviceShort}' + storageAccountName: 'dep${namePrefix}st${serviceShort}' + hybridConnectionName: 'dep-${namePrefix}-hc-${serviceShort}' + location: resourceLocation + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-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 + } +} + +// ============== // +// 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 + kind: 'app,linux' + serverFarmResourceId: nestedDependencies.outputs.serverFarmResourceId + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + httpsOnly: true + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + slots: [ + { + name: 'slot1' + diagnosticSettings: [ + { + name: 'customSetting' + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + privateEndpoints: [ + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + service: 'sites-slot1' + } + ] + basicPublishingCredentialsPolicies: [ + { + name: 'ftp' + allow: false + } + { + name: 'scm' + allow: false + } + ] + 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' + } + ] + siteConfig: { + alwaysOn: true + metadata: [ + { + name: 'CURRENT_STACK' + value: 'dotnetcore' + } + ] + } + storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + storageAccountUseIdentityAuthentication: true + hybridConnectionRelays: [ + { + resourceId: nestedDependencies.outputs.hybridConnectionResourceId + sendKeyName: 'defaultSender' + } + ] + } + { + name: 'slot2' + basicPublishingCredentialsPolicies: [ + { + name: 'ftp' + } + { + name: 'scm' + } + ] + storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + storageAccountUseIdentityAuthentication: true + } + ] + privateEndpoints: [ + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + } + ] + 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' + } + ] + siteConfig: { + alwaysOn: true + metadata: [ + { + name: 'CURRENT_STACK' + value: 'dotnetcore' + } + ] + } + storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + storageAccountUseIdentityAuthentication: true + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + basicPublishingCredentialsPolicies: [ + { + name: 'ftp' + allow: false + } + { + name: 'scm' + allow: false + } + + ] + hybridConnectionRelays: [ + { + resourceId: nestedDependencies.outputs.hybridConnectionResourceId + sendKeyName: 'defaultSender' + } + ] + scmSiteAlsoStopped: true + vnetContentShareEnabled: true + vnetImagePullEnabled: true + vnetRouteAllEnabled: true + publicNetworkAccess: 'Disabled' + } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] +}] From 792d5be4504c0ed66304d99d90bc3cc3fc3a1f84 Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Thu, 21 Mar 2024 15:37:44 +0000 Subject: [PATCH 49/73] feat: add AZ parameter checks for zonal resources (#1365) ## Description Adding AZ parameter checks for zonal resoruces. Only NAT GW Module is the one to have tests added at this time. ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.network.nat-gateways](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.nat-gateway.yml/badge.svg)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.res.network.nat-gateway.yml) | > Failure is expected as the module is not compliant ## Type of Change - [x] Update to CI Environment or utlities (Non-module effecting changes) - [ ] Azure Verified Module updates: - [ ] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [ ] I have run `Set-AVMModule` locally to generate the supporting module files. - [ ] My corresponding pipelines / checks run clean and green without any errors or warnings --- .../tests/unit/avm.core.team.tests.ps1 | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 avm/res/network/nat-gateway/tests/unit/avm.core.team.tests.ps1 diff --git a/avm/res/network/nat-gateway/tests/unit/avm.core.team.tests.ps1 b/avm/res/network/nat-gateway/tests/unit/avm.core.team.tests.ps1 new file mode 100644 index 0000000000..8d3eb0180d --- /dev/null +++ b/avm/res/network/nat-gateway/tests/unit/avm.core.team.tests.ps1 @@ -0,0 +1,40 @@ +<# +.SYNOPSIS +This file contains Pester tests that the AVM Core Team has written for the module. Any additions or changes to these tests will need to be reviewed by the AVM Core Team, this is handled by CODEOWNERS. + +If you wish to add your own Pester tests for you module create a new .tests.ps1 file in the /tests/unit folder of your module. +#> + +param ( + [Parameter(Mandatory = $false)] + [array] $moduleFolderPaths, + + [Parameter(Mandatory = $false)] + [string] $repoRootPath +) + +BeforeAll { + . (Join-Path $RepoRootPath 'avm' 'utilities' 'pipelines' 'sharedScripts' 'helper' 'Get-IsParameterRequired.ps1') + + if ($moduleFolderPaths.Count -gt 1) { + $topLevelModuleTemplatePath = $moduleFolderPaths | Sort-Object | Select-Object -First 1 + } + else { + $topLevelModuleTemplatePath = $moduleFolderPaths + } + + $moduleJsonContentHashtable = Get-Content -Path (Join-Path $topLevelModuleTemplatePath 'main.json') | ConvertFrom-Json -AsHashtable +} + +Describe 'AVM Core Team Module Specific Tests' { + + Context 'WAF - Reliability Pillar - Parameter Tests' { + + It 'NAT Gateway Module Availability Zone Parameter Should Not Have A Default Value Set' { + $isRequired = Get-IsParameterRequired -TemplateFileContent $moduleJsonContentHashtable -Parameter $moduleJsonContentHashtable.parameters.zones + $isRequired | Should -Be $true + } + + } + +} From 07951adc93b5f5b77869dcb0c3474353d9c0c7fe Mon Sep 17 00:00:00 2001 From: Alexander Sehr Date: Thu, 21 Mar 2024 17:51:42 +0100 Subject: [PATCH 50/73] fix: Enabled readme generation script to handle V2 Bicep formatter (#1321) ## Description - Enabled readme generation script to handle V2 Bicep formatter (introduced via 0.26.54) ## Pipeline Reference | Pipeline | | -------- | | | --------- Co-authored-by: Erika Gressi <56914614+eriqua@users.noreply.github.com> Co-authored-by: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> --- avm/res/analysis-services/server/README.md | 6 +- avm/res/api-management/service/README.md | 14 +- .../configuration-store/README.md | 10 +- avm/res/app/container-app/README.md | 6 +- avm/res/app/managed-environment/README.md | 6 +- .../automation/automation-account/README.md | 8 +- avm/res/batch/batch-account/README.md | 8 +- avm/res/cache/redis/README.md | 6 +- avm/res/cdn/profile/README.md | 8 +- avm/res/cognitive-services/account/README.md | 12 +- avm/res/compute/availability-set/README.md | 6 +- avm/res/compute/disk-encryption-set/README.md | 8 +- avm/res/compute/disk/README.md | 10 +- avm/res/compute/gallery/README.md | 6 +- avm/res/compute/image/README.md | 6 +- .../proximity-placement-group/README.md | 6 +- avm/res/compute/ssh-public-key/README.md | 6 +- .../virtual-machine-scale-set/README.md | 12 +- avm/res/compute/virtual-machine/README.md | 14 +- avm/res/consumption/budget/README.md | 6 +- avm/res/container-registry/registry/README.md | 8 +- .../managed-cluster/README.md | 18 +- avm/res/data-factory/factory/README.md | 6 +- .../data-protection/backup-vault/README.md | 6 +- avm/res/databricks/access-connector/README.md | 6 +- avm/res/databricks/workspace/README.md | 6 +- .../db-for-my-sql/flexible-server/README.md | 8 +- .../flexible-server/README.md | 10 +- .../application-group/README.md | 6 +- .../host-pool/README.md | 6 +- .../scaling-plan/README.md | 6 +- .../workspace/README.md | 6 +- avm/res/dev-test-lab/lab/README.md | 6 +- .../document-db/database-account/README.md | 30 +- avm/res/event-grid/domain/README.md | 6 +- avm/res/event-grid/namespace/README.md | 10 +- avm/res/event-grid/system-topic/README.md | 6 +- avm/res/event-grid/topic/README.md | 6 +- avm/res/event-hub/namespace/README.md | 8 +- avm/res/health-bot/health-bot/README.md | 6 +- avm/res/insights/action-group/README.md | 6 +- avm/res/insights/activity-log-alert/README.md | 6 +- avm/res/insights/component/README.md | 6 +- .../data-collection-endpoint/README.md | 6 +- .../insights/data-collection-rule/README.md | 16 +- avm/res/insights/diagnostic-setting/README.md | 6 +- avm/res/insights/metric-alert/README.md | 6 +- avm/res/insights/private-link-scope/README.md | 9 +- .../insights/scheduled-query-rule/README.md | 6 +- avm/res/insights/webtest/README.md | 6 +- avm/res/key-vault/vault/README.md | 6 +- .../key-vault/vault/access-policy/main.json | 4 +- avm/res/key-vault/vault/key/main.json | 4 +- avm/res/key-vault/vault/main.json | 16 +- avm/res/key-vault/vault/secret/main.json | 4 +- .../vault/tests/e2e/defaults/main.test.bicep | 20 +- .../vault/tests/e2e/max/main.test.bicep | 404 +++++++++--------- .../tests/e2e/waf-aligned/main.test.bicep | 156 +++---- .../extension/README.md | 10 +- .../flux-configuration/README.md | 18 +- avm/res/logic/workflow/README.md | 6 +- .../workspace/README.md | 8 +- .../maintenance-configuration/README.md | 14 +- .../user-assigned-identity/README.md | 6 +- avm/res/management/management-group/README.md | 6 +- avm/res/net-app/net-app-account/README.md | 14 +- .../application-security-group/README.md | 6 +- avm/res/network/azure-firewall/README.md | 14 +- avm/res/network/bastion-host/README.md | 8 +- avm/res/network/connection/README.md | 6 +- .../network/ddos-protection-plan/README.md | 6 +- .../network/dns-forwarding-ruleset/README.md | 6 +- avm/res/network/dns-resolver/README.md | 6 +- avm/res/network/dns-zone/README.md | 6 +- .../network/express-route-circuit/README.md | 7 +- .../network/express-route-gateway/README.md | 6 +- avm/res/network/firewall-policy/README.md | 6 +- .../README.md | 6 +- avm/res/network/front-door/README.md | 6 +- avm/res/network/ip-group/README.md | 6 +- avm/res/network/load-balancer/README.md | 8 +- .../network/local-network-gateway/README.md | 6 +- avm/res/network/nat-gateway/README.md | 8 +- avm/res/network/network-interface/README.md | 6 +- avm/res/network/network-manager/README.md | 6 +- .../network/network-security-group/README.md | 6 +- avm/res/network/private-dns-zone/README.md | 6 +- avm/res/network/private-endpoint/README.md | 6 +- .../network/private-link-service/README.md | 6 +- avm/res/network/public-ip-address/README.md | 6 +- avm/res/network/public-ip-prefix/README.md | 6 +- avm/res/network/route-table/README.md | 6 +- .../network/trafficmanagerprofile/README.md | 6 +- avm/res/network/virtual-hub/README.md | 6 +- .../network/virtual-network-gateway/README.md | 12 +- avm/res/network/virtual-network/README.md | 8 +- avm/res/network/virtual-wan/README.md | 6 +- avm/res/network/vpn-gateway/README.md | 6 +- avm/res/network/vpn-site/README.md | 6 +- .../operational-insights/workspace/README.md | 8 +- .../operations-management/solution/README.md | 8 +- avm/res/power-bi-dedicated/capacity/README.md | 6 +- avm/res/purview/account/README.md | 6 +- avm/res/resource-graph/query/README.md | 6 +- avm/res/resources/deployment-script/README.md | 12 +- avm/res/resources/resource-group/README.md | 6 +- avm/res/search/search-service/README.md | 8 +- avm/res/service-bus/namespace/README.md | 8 +- avm/res/signal-r-service/signal-r/README.md | 6 +- .../signal-r-service/web-pub-sub/README.md | 6 +- avm/res/sql/server/README.md | 12 +- avm/res/storage/storage-account/README.md | 18 +- avm/res/synapse/private-link-hub/README.md | 6 +- avm/res/synapse/workspace/README.md | 12 +- .../image-template/README.md | 6 +- avm/res/web/serverfarm/README.md | 6 +- avm/res/web/site/README.md | 10 +- avm/res/web/static-site/README.md | 6 +- .../sharedScripts/Set-ModuleReadMe.ps1 | 168 +++++--- 119 files changed, 869 insertions(+), 779 deletions(-) diff --git a/avm/res/analysis-services/server/README.md b/avm/res/analysis-services/server/README.md index 8b399c205a..5d83348f2f 100644 --- a/avm/res/analysis-services/server/README.md +++ b/avm/res/analysis-services/server/README.md @@ -48,7 +48,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module server 'br/public:avm/res/analysis-services/server:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-assmin' + name: 'serverDeployment' params: { // Required parameters name: 'assmin' @@ -96,7 +96,7 @@ This instance deploys the module with most of its features enabled. ```bicep module server 'br/public:avm/res/analysis-services/server:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-assmax' + name: 'serverDeployment' params: { // Required parameters name: 'assmax' @@ -278,7 +278,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module server 'br/public:avm/res/analysis-services/server:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-asswaf' + name: 'serverDeployment' params: { // Required parameters name: 'asswaf' diff --git a/avm/res/api-management/service/README.md b/avm/res/api-management/service/README.md index 751e823427..4b29ffb6c3 100644 --- a/avm/res/api-management/service/README.md +++ b/avm/res/api-management/service/README.md @@ -58,7 +58,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module service 'br/public:avm/res/api-management/service:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-apismin' + name: 'serviceDeployment' params: { // Required parameters name: 'apismin001' @@ -114,7 +114,7 @@ This instance deploys the module with most of its features enabled. ```bicep module service 'br/public:avm/res/api-management/service:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-apismax' + name: 'serviceDeployment' params: { // Required parameters name: 'apismax001' @@ -274,6 +274,7 @@ module service 'br/public:avm/res/api-management/service:' = { subscriptions: [ { name: 'testArmSubscriptionAllApis' + scope: '/apis' } ] tags: { @@ -489,7 +490,8 @@ module service 'br/public:avm/res/api-management/service:' = { "subscriptions": { "value": [ { - "name": "testArmSubscriptionAllApis" + "name": "testArmSubscriptionAllApis", + "scope": "/apis" } ] }, @@ -518,7 +520,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module service 'br/public:avm/res/api-management/service:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-apiswaf' + name: 'serviceDeployment' params: { // Required parameters name: 'apiswaf001' @@ -667,6 +669,7 @@ module service 'br/public:avm/res/api-management/service:' = { subscriptions: [ { name: 'testArmSubscriptionAllApis' + scope: '/apis' } ] tags: { @@ -869,7 +872,8 @@ module service 'br/public:avm/res/api-management/service:' = { "subscriptions": { "value": [ { - "name": "testArmSubscriptionAllApis" + "name": "testArmSubscriptionAllApis", + "scope": "/apis" } ] }, diff --git a/avm/res/app-configuration/configuration-store/README.md b/avm/res/app-configuration/configuration-store/README.md index da6911a272..c7d931c225 100644 --- a/avm/res/app-configuration/configuration-store/README.md +++ b/avm/res/app-configuration/configuration-store/README.md @@ -53,7 +53,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module configurationStore 'br/public:avm/res/app-configuration/configuration-store:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-accmin' + name: 'configurationStoreDeployment' params: { // Required parameters name: 'accmin001' @@ -101,7 +101,7 @@ This instance deploys the module using Customer-Managed-Keys using a User-Assign ```bicep module configurationStore 'br/public:avm/res/app-configuration/configuration-store:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-accencr' + name: 'configurationStoreDeployment' params: { // Required parameters name: 'accencr001' @@ -219,7 +219,7 @@ This instance deploys the module with most of its features enabled. ```bicep module configurationStore 'br/public:avm/res/app-configuration/configuration-store:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-accmax' + name: 'configurationStoreDeployment' params: { // Required parameters name: 'accmax001' @@ -423,7 +423,7 @@ This instance deploys the module with private endpoints. ```bicep module configurationStore 'br/public:avm/res/app-configuration/configuration-store:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-accpe' + name: 'configurationStoreDeployment' params: { // Required parameters name: 'accpe001' @@ -527,7 +527,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module configurationStore 'br/public:avm/res/app-configuration/configuration-store:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-accwaf' + name: 'configurationStoreDeployment' params: { // Required parameters name: 'accwaf001' diff --git a/avm/res/app/container-app/README.md b/avm/res/app/container-app/README.md index 3c3848ada9..4baab36177 100644 --- a/avm/res/app/container-app/README.md +++ b/avm/res/app/container-app/README.md @@ -42,7 +42,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module containerApp 'br/public:avm/res/app/container-app:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-acamin' + name: 'containerAppDeployment' params: { // Required parameters containers: [ @@ -116,7 +116,7 @@ This instance deploys the module with most of its features enabled. ```bicep module containerApp 'br/public:avm/res/app/container-app:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-acamax' + name: 'containerAppDeployment' params: { // Required parameters containers: [ @@ -310,7 +310,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module containerApp 'br/public:avm/res/app/container-app:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-acawaf' + name: 'containerAppDeployment' params: { // Required parameters containers: [ diff --git a/avm/res/app/managed-environment/README.md b/avm/res/app/managed-environment/README.md index 5fb9b4973f..b91247a73e 100644 --- a/avm/res/app/managed-environment/README.md +++ b/avm/res/app/managed-environment/README.md @@ -42,7 +42,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module managedEnvironment 'br/public:avm/res/app/managed-environment:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-amemin' + name: 'managedEnvironmentDeployment' params: { // Required parameters logAnalyticsWorkspaceResourceId: '' @@ -94,7 +94,7 @@ This instance deploys the module with most of its features enabled. ```bicep module managedEnvironment 'br/public:avm/res/app/managed-environment:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-amemax' + name: 'managedEnvironmentDeployment' params: { // Required parameters logAnalyticsWorkspaceResourceId: '' @@ -244,7 +244,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module managedEnvironment 'br/public:avm/res/app/managed-environment:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-amewaf' + name: 'managedEnvironmentDeployment' params: { // Required parameters logAnalyticsWorkspaceResourceId: '' diff --git a/avm/res/automation/automation-account/README.md b/avm/res/automation/automation-account/README.md index 5f85d48d81..d6b47af404 100644 --- a/avm/res/automation/automation-account/README.md +++ b/avm/res/automation/automation-account/README.md @@ -54,7 +54,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module automationAccount 'br/public:avm/res/automation/automation-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-aamin' + name: 'automationAccountDeployment' params: { // Required parameters name: 'aamin001' @@ -102,7 +102,7 @@ This instance deploys the module using Customer-Managed-Keys using a User-Assign ```bicep module automationAccount 'br/public:avm/res/automation/automation-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-aaencr' + name: 'automationAccountDeployment' params: { // Required parameters name: 'aaencr001' @@ -174,7 +174,7 @@ This instance deploys the module with most of its features enabled. ```bicep module automationAccount 'br/public:avm/res/automation/automation-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-aamax' + name: 'automationAccountDeployment' params: { // Required parameters name: 'aamax001' @@ -662,7 +662,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module automationAccount 'br/public:avm/res/automation/automation-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-aawaf' + name: 'automationAccountDeployment' params: { // Required parameters name: 'aawaf001' diff --git a/avm/res/batch/batch-account/README.md b/avm/res/batch/batch-account/README.md index 131c5571fc..2c137096cd 100644 --- a/avm/res/batch/batch-account/README.md +++ b/avm/res/batch/batch-account/README.md @@ -46,7 +46,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module batchAccount 'br/public:avm/res/batch/batch-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-bbamin' + name: 'batchAccountDeployment' params: { // Required parameters name: 'bbamin001' @@ -98,7 +98,7 @@ This instance deploys the module using Customer-Managed-Keys using a User-Assign ```bicep module batchAccount 'br/public:avm/res/batch/batch-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-bbaencr' + name: 'batchAccountDeployment' params: { // Required parameters name: 'bbaencr001' @@ -188,7 +188,7 @@ This instance deploys the module with most of its features enabled. ```bicep module batchAccount 'br/public:avm/res/batch/batch-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-bbamax' + name: 'batchAccountDeployment' params: { // Required parameters name: 'bbamax001' @@ -504,7 +504,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module batchAccount 'br/public:avm/res/batch/batch-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-bbawaf' + name: 'batchAccountDeployment' params: { // Required parameters name: 'bbawaf001' diff --git a/avm/res/cache/redis/README.md b/avm/res/cache/redis/README.md index 4414d3a7b6..7603c3c39d 100644 --- a/avm/res/cache/redis/README.md +++ b/avm/res/cache/redis/README.md @@ -46,7 +46,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module redis 'br/public:avm/res/cache/redis:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-crmin' + name: 'redisDeployment' params: { // Required parameters name: 'crmin001' @@ -94,7 +94,7 @@ This instance deploys the module with most of its features enabled. ```bicep module redis 'br/public:avm/res/cache/redis:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-crmax' + name: 'redisDeployment' params: { // Required parameters name: 'crmax001' @@ -354,7 +354,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module redis 'br/public:avm/res/cache/redis:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-crwaf' + name: 'redisDeployment' params: { // Required parameters name: 'crwaf001' diff --git a/avm/res/cdn/profile/README.md b/avm/res/cdn/profile/README.md index 39ea759b35..826e2450fe 100644 --- a/avm/res/cdn/profile/README.md +++ b/avm/res/cdn/profile/README.md @@ -53,7 +53,7 @@ This instance deploys the module as Azure Front Door. ```bicep module profile 'br/public:avm/res/cdn/profile:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cdnpafd' + name: 'profileDeployment' params: { // Required parameters name: 'dep-test-cdnpafd' @@ -243,7 +243,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module profile 'br/public:avm/res/cdn/profile:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cdnpmin' + name: 'profileDeployment' params: { // Required parameters name: 'dep-test-cdnpmin' @@ -295,7 +295,7 @@ This instance deploys the module with most of its features enabled. ```bicep module profile 'br/public:avm/res/cdn/profile:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cdnpmax' + name: 'profileDeployment' params: { // Required parameters name: 'dep-test-cdnpmax' @@ -459,7 +459,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module profile 'br/public:avm/res/cdn/profile:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cdnpwaf' + name: 'profileDeployment' params: { // Required parameters name: 'dep-test-cdnpwaf' diff --git a/avm/res/cognitive-services/account/README.md b/avm/res/cognitive-services/account/README.md index 7fb0da5818..fdcbfc8be0 100644 --- a/avm/res/cognitive-services/account/README.md +++ b/avm/res/cognitive-services/account/README.md @@ -48,7 +48,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module account 'br/public:avm/res/cognitive-services/account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-csamin' + name: 'accountDeployment' params: { // Required parameters kind: 'SpeechServices' @@ -100,7 +100,7 @@ This instance deploys the module with most of its features enabled. ```bicep module account 'br/public:avm/res/cognitive-services/account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-csamax' + name: 'accountDeployment' params: { // Required parameters kind: 'Face' @@ -388,7 +388,7 @@ This instance deploys the module as a Speech Service. ```bicep module account 'br/public:avm/res/cognitive-services/account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-csaspeech' + name: 'accountDeployment' params: { // Required parameters kind: 'SpeechServices' @@ -502,7 +502,7 @@ This instance deploys the module using Customer-Managed-Keys using a System-Assi ```bicep module account 'br/public:avm/res/cognitive-services/account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-csaecrs' + name: 'accountDeployment' params: { // Required parameters kind: 'SpeechServices' @@ -584,7 +584,7 @@ This instance deploys the module using Customer-Managed-Keys using a User-Assign ```bicep module account 'br/public:avm/res/cognitive-services/account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-csaencr' + name: 'accountDeployment' params: { // Required parameters kind: 'SpeechServices' @@ -672,7 +672,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module account 'br/public:avm/res/cognitive-services/account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-csawaf' + name: 'accountDeployment' params: { // Required parameters kind: 'Face' diff --git a/avm/res/compute/availability-set/README.md b/avm/res/compute/availability-set/README.md index e98bc236b5..5d9c10ce6c 100644 --- a/avm/res/compute/availability-set/README.md +++ b/avm/res/compute/availability-set/README.md @@ -42,7 +42,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module availabilitySet 'br/public:avm/res/compute/availability-set:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-casmin' + name: 'availabilitySetDeployment' params: { // Required parameters name: 'casmin001' @@ -90,7 +90,7 @@ This instance deploys the module with most of its features enabled. ```bicep module availabilitySet 'br/public:avm/res/compute/availability-set:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-casmax' + name: 'availabilitySetDeployment' params: { // Required parameters name: 'casmax001' @@ -200,7 +200,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module availabilitySet 'br/public:avm/res/compute/availability-set:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-caswaf' + name: 'availabilitySetDeployment' params: { // Required parameters name: 'caswaf001' diff --git a/avm/res/compute/disk-encryption-set/README.md b/avm/res/compute/disk-encryption-set/README.md index 3ebad4632b..8cc108d0f5 100644 --- a/avm/res/compute/disk-encryption-set/README.md +++ b/avm/res/compute/disk-encryption-set/README.md @@ -44,7 +44,7 @@ This instance uses a Key Vault with the Access Policy permission model. If no pe ```bicep module diskEncryptionSet 'br/public:avm/res/compute/disk-encryption-set:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cdesap' + name: 'diskEncryptionSetDeployment' params: { // Required parameters keyName: '' @@ -162,7 +162,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module diskEncryptionSet 'br/public:avm/res/compute/disk-encryption-set:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cdesmin' + name: 'diskEncryptionSetDeployment' params: { // Required parameters keyName: '' @@ -218,7 +218,7 @@ This instance deploys the module with most of its features enabled. ```bicep module diskEncryptionSet 'br/public:avm/res/compute/disk-encryption-set:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cdesmax' + name: 'diskEncryptionSetDeployment' params: { // Required parameters keyName: '' @@ -344,7 +344,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module diskEncryptionSet 'br/public:avm/res/compute/disk-encryption-set:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cdeswaf' + name: 'diskEncryptionSetDeployment' params: { // Required parameters keyName: '' diff --git a/avm/res/compute/disk/README.md b/avm/res/compute/disk/README.md index 59deb4cd0b..a84e7810a8 100644 --- a/avm/res/compute/disk/README.md +++ b/avm/res/compute/disk/README.md @@ -44,7 +44,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module disk 'br/public:avm/res/compute/disk:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cdmin' + name: 'diskDeployment' params: { // Required parameters name: 'cdmin001' @@ -100,7 +100,7 @@ This instance deploys the module with an image reference. ```bicep module disk 'br/public:avm/res/compute/disk:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cdimg' + name: 'diskDeployment' params: { // Required parameters name: 'cdimg001' @@ -160,7 +160,7 @@ This instance deploys the module with a custom image that is imported from a VHD ```bicep module disk 'br/public:avm/res/compute/disk:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cdimp' + name: 'diskDeployment' params: { // Required parameters name: 'cdimp001' @@ -224,7 +224,7 @@ This instance deploys the module with most of its features enabled. ```bicep module disk 'br/public:avm/res/compute/disk:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cdmax' + name: 'diskDeployment' params: { // Required parameters name: 'cdmax001' @@ -358,7 +358,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module disk 'br/public:avm/res/compute/disk:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cdwaf' + name: 'diskDeployment' params: { // Required parameters name: 'cdwaf001' diff --git a/avm/res/compute/gallery/README.md b/avm/res/compute/gallery/README.md index fcb389cc6e..081835b82b 100644 --- a/avm/res/compute/gallery/README.md +++ b/avm/res/compute/gallery/README.md @@ -44,7 +44,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module gallery 'br/public:avm/res/compute/gallery:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cgmin' + name: 'galleryDeployment' params: { // Required parameters name: 'cgmin001' @@ -92,7 +92,7 @@ This instance deploys the module with most of its features enabled. ```bicep module gallery 'br/public:avm/res/compute/gallery:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cgmax' + name: 'galleryDeployment' params: { // Required parameters name: 'cgmax001' @@ -382,7 +382,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module gallery 'br/public:avm/res/compute/gallery:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cgwaf' + name: 'galleryDeployment' params: { // Required parameters name: 'cgwaf001' diff --git a/avm/res/compute/image/README.md b/avm/res/compute/image/README.md index 7534e86119..1f3e26e39b 100644 --- a/avm/res/compute/image/README.md +++ b/avm/res/compute/image/README.md @@ -41,7 +41,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module image 'br/public:avm/res/compute/image:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cimin' + name: 'imageDeployment' params: { // Required parameters name: 'cimin001' @@ -105,7 +105,7 @@ This instance deploys the module with most of its features enabled. ```bicep module image 'br/public:avm/res/compute/image:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cimax' + name: 'imageDeployment' params: { // Required parameters name: 'cimax001' @@ -237,7 +237,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module image 'br/public:avm/res/compute/image:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ciwaf' + name: 'imageDeployment' params: { // Required parameters name: 'ciwaf001' diff --git a/avm/res/compute/proximity-placement-group/README.md b/avm/res/compute/proximity-placement-group/README.md index 355d7cba0d..fc052ff287 100644 --- a/avm/res/compute/proximity-placement-group/README.md +++ b/avm/res/compute/proximity-placement-group/README.md @@ -42,7 +42,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module proximityPlacementGroup 'br/public:avm/res/compute/proximity-placement-group:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cppgmin' + name: 'proximityPlacementGroupDeployment' params: { // Required parameters name: 'cppgmin001' @@ -90,7 +90,7 @@ This instance deploys the module with most of its features enabled. ```bicep module proximityPlacementGroup 'br/public:avm/res/compute/proximity-placement-group:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cppgmax' + name: 'proximityPlacementGroupDeployment' params: { // Required parameters name: 'cppgmax001' @@ -236,7 +236,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module proximityPlacementGroup 'br/public:avm/res/compute/proximity-placement-group:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cppgwaf' + name: 'proximityPlacementGroupDeployment' params: { // Required parameters name: 'cppgwaf001' diff --git a/avm/res/compute/ssh-public-key/README.md b/avm/res/compute/ssh-public-key/README.md index ec1cf6c06c..27ded42618 100644 --- a/avm/res/compute/ssh-public-key/README.md +++ b/avm/res/compute/ssh-public-key/README.md @@ -44,7 +44,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module sshPublicKey 'br/public:avm/res/compute/ssh-public-key:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cspkmin' + name: 'sshPublicKeyDeployment' params: { // Required parameters name: 'cspkmin001' @@ -92,7 +92,7 @@ This instance deploys the module with most of its features enabled. ```bicep module sshPublicKey 'br/public:avm/res/compute/ssh-public-key:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cspkmax' + name: 'sshPublicKeyDeployment' params: { // Required parameters name: 'sshkey-cspkmax001' @@ -206,7 +206,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module sshPublicKey 'br/public:avm/res/compute/ssh-public-key:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cspkwaf' + name: 'sshPublicKeyDeployment' params: { // Required parameters name: 'sshkey-cspkwaf001' diff --git a/avm/res/compute/virtual-machine-scale-set/README.md b/avm/res/compute/virtual-machine-scale-set/README.md index d0bcbadcae..96b8ddefeb 100644 --- a/avm/res/compute/virtual-machine-scale-set/README.md +++ b/avm/res/compute/virtual-machine-scale-set/README.md @@ -47,7 +47,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module virtualMachineScaleSet 'br/public:avm/res/compute/virtual-machine-scale-set:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cvmsslinmin' + name: 'virtualMachineScaleSetDeployment' params: { // Required parameters adminUsername: 'scaleSetAdmin' @@ -187,7 +187,7 @@ This instance deploys the module with most of its features enabled. ```bicep module virtualMachineScaleSet 'br/public:avm/res/compute/virtual-machine-scale-set:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cvmsslinmax' + name: 'virtualMachineScaleSetDeployment' params: { // Required parameters adminUsername: 'scaleSetAdmin' @@ -561,7 +561,7 @@ This instance deploys the module with disk enryption set. ```bicep module virtualMachineScaleSet 'br/public:avm/res/compute/virtual-machine-scale-set:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cvmsslcmk' + name: 'virtualMachineScaleSetDeployment' params: { // Required parameters adminUsername: 'scaleSetAdmin' @@ -743,7 +743,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module virtualMachineScaleSet 'br/public:avm/res/compute/virtual-machine-scale-set:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cvmsswinmin' + name: 'virtualMachineScaleSetDeployment' params: { // Required parameters adminUsername: 'localAdminUser' @@ -869,7 +869,7 @@ This instance deploys the module with most of its features enabled. ```bicep module virtualMachineScaleSet 'br/public:avm/res/compute/virtual-machine-scale-set:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cvmsswinmax' + name: 'virtualMachineScaleSetDeployment' params: { // Required parameters adminUsername: 'localAdminUser' @@ -1221,7 +1221,7 @@ This instance deploys the module in alignment with the best-practices of the Wel ```bicep module virtualMachineScaleSet 'br/public:avm/res/compute/virtual-machine-scale-set:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cvmsswinwaf' + name: 'virtualMachineScaleSetDeployment' params: { // Required parameters adminUsername: 'localAdminUser' diff --git a/avm/res/compute/virtual-machine/README.md b/avm/res/compute/virtual-machine/README.md index 628d64515c..40fead100f 100644 --- a/avm/res/compute/virtual-machine/README.md +++ b/avm/res/compute/virtual-machine/README.md @@ -53,7 +53,7 @@ This instance deploys the module with registering to an automation account. ```bicep module virtualMachine 'br/public:avm/res/compute/virtual-machine:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cvmlinatmg' + name: 'virtualMachineDeployment' params: { // Required parameters adminUsername: 'localAdminUser' @@ -203,7 +203,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module virtualMachine 'br/public:avm/res/compute/virtual-machine:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cvmlinmin' + name: 'virtualMachineDeployment' params: { // Required parameters adminUsername: 'localAdminUser' @@ -341,7 +341,7 @@ This instance deploys the module with most of its features enabled. ```bicep module virtualMachine 'br/public:avm/res/compute/virtual-machine:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cvmlinmax' + name: 'virtualMachineDeployment' params: { // Required parameters adminUsername: 'localAdministrator' @@ -913,7 +913,7 @@ This instance deploys the module in alignment with the best-practices of the Wel ```bicep module virtualMachine 'br/public:avm/res/compute/virtual-machine:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cvmwinwaf' + name: 'virtualMachineDeployment' params: { // Required parameters adminUsername: 'VMAdmin' @@ -1521,7 +1521,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module virtualMachine 'br/public:avm/res/compute/virtual-machine:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cvmwinmin' + name: 'virtualMachineDeployment' params: { // Required parameters adminUsername: 'localAdminUser' @@ -1639,7 +1639,7 @@ This instance deploys the module with most of its features enabled. ```bicep module virtualMachine 'br/public:avm/res/compute/virtual-machine:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cvmwinmax' + name: 'virtualMachineDeployment' params: { // Required parameters adminUsername: 'VMAdmin' @@ -2249,7 +2249,7 @@ This instance deploys the module with disk enryption set. ```bicep module virtualMachine 'br/public:avm/res/compute/virtual-machine:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cvmwincmk' + name: 'virtualMachineDeployment' params: { // Required parameters adminUsername: 'VMAdministrator' diff --git a/avm/res/consumption/budget/README.md b/avm/res/consumption/budget/README.md index b87483a79b..0398dc54fb 100644 --- a/avm/res/consumption/budget/README.md +++ b/avm/res/consumption/budget/README.md @@ -40,7 +40,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module budget 'br/public:avm/res/consumption/budget:' = { - name: '${uniqueString(deployment().name)}-test-cbmin' + name: 'budgetDeployment' params: { // Required parameters amount: 500 @@ -100,7 +100,7 @@ This instance deploys the module with most of its features enabled. ```bicep module budget 'br/public:avm/res/consumption/budget:' = { - name: '${uniqueString(deployment().name)}-test-cbmax' + name: 'budgetDeployment' params: { // Required parameters amount: 500 @@ -186,7 +186,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module budget 'br/public:avm/res/consumption/budget:' = { - name: '${uniqueString(deployment().name)}-test-cbwaf' + name: 'budgetDeployment' params: { // Required parameters amount: 500 diff --git a/avm/res/container-registry/registry/README.md b/avm/res/container-registry/registry/README.md index c9c60eb79c..cd49ff7b18 100644 --- a/avm/res/container-registry/registry/README.md +++ b/avm/res/container-registry/registry/README.md @@ -49,7 +49,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module registry 'br/public:avm/res/container-registry/registry:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-crrmin' + name: 'registryDeployment' params: { // Required parameters name: 'crrmin001' @@ -97,7 +97,7 @@ This instance deploys the module using Customer-Managed-Keys using a User-Assign ```bicep module registry 'br/public:avm/res/container-registry/registry:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-crrencr' + name: 'registryDeployment' params: { // Required parameters name: 'crrencr001' @@ -177,7 +177,7 @@ This instance deploys the module with most of its features enabled. ```bicep module registry 'br/public:avm/res/container-registry/registry:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-crrmax' + name: 'registryDeployment' params: { // Required parameters name: 'crrmax001' @@ -463,7 +463,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module registry 'br/public:avm/res/container-registry/registry:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-crrwaf' + name: 'registryDeployment' params: { // Required parameters name: 'crrwaf001' diff --git a/avm/res/container-service/managed-cluster/README.md b/avm/res/container-service/managed-cluster/README.md index 13cfd48fce..36e74a78b9 100644 --- a/avm/res/container-service/managed-cluster/README.md +++ b/avm/res/container-service/managed-cluster/README.md @@ -48,7 +48,7 @@ This instance deploys the module with Azure CNI network plugin . ```bicep module managedCluster 'br/public:avm/res/container-service/managed-cluster:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-csmaz' + name: 'managedClusterDeployment' params: { // Required parameters name: 'csmaz001' @@ -168,6 +168,7 @@ module managedCluster 'br/public:avm/res/container-service/managed-cluster:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-csmin' + name: 'managedClusterDeployment' params: { // Required parameters name: 'csmin001' @@ -626,7 +630,7 @@ This instance deploys the module with Kubenet network plugin . ```bicep module managedCluster 'br/public:avm/res/container-service/managed-cluster:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-csmkube' + name: 'managedClusterDeployment' params: { // Required parameters name: 'csmkube001' @@ -906,7 +910,7 @@ This instance deploys the module with a private cluster instance. ```bicep module managedCluster 'br/public:avm/res/container-service/managed-cluster:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-csmpriv' + name: 'managedClusterDeployment' params: { // Required parameters name: 'csmpriv001' @@ -1132,7 +1136,7 @@ This instance deploys the module in alignment with the best-practices of the Wel ```bicep module managedCluster 'br/public:avm/res/container-service/managed-cluster:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-cswaf' + name: 'managedClusterDeployment' params: { // Required parameters name: 'cswaf001' diff --git a/avm/res/data-factory/factory/README.md b/avm/res/data-factory/factory/README.md index 420af9f1e4..9da7d320bd 100644 --- a/avm/res/data-factory/factory/README.md +++ b/avm/res/data-factory/factory/README.md @@ -49,7 +49,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module factory 'br/public:avm/res/data-factory/factory:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dffmin' + name: 'factoryDeployment' params: { // Required parameters name: 'dffmin001' @@ -97,7 +97,7 @@ This instance deploys the module with most of its features enabled. ```bicep module factory 'br/public:avm/res/data-factory/factory:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dffmax' + name: 'factoryDeployment' params: { // Required parameters name: 'dffmax001' @@ -375,7 +375,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module factory 'br/public:avm/res/data-factory/factory:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dffwaf' + name: 'factoryDeployment' params: { // Required parameters name: 'dffwaf001' diff --git a/avm/res/data-protection/backup-vault/README.md b/avm/res/data-protection/backup-vault/README.md index fc84b5d52f..f4ec188a97 100644 --- a/avm/res/data-protection/backup-vault/README.md +++ b/avm/res/data-protection/backup-vault/README.md @@ -44,7 +44,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module backupVault 'br/public:avm/res/data-protection/backup-vault:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dpbvmin' + name: 'backupVaultDeployment' params: { // Required parameters name: 'dpbvmin001' @@ -92,7 +92,7 @@ This instance deploys the module with most of its features enabled. ```bicep module backupVault 'br/public:avm/res/data-protection/backup-vault:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dpbvmax' + name: 'backupVaultDeployment' params: { // Required parameters name: 'dpbvmax001' @@ -336,7 +336,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module backupVault 'br/public:avm/res/data-protection/backup-vault:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dpbvwaf' + name: 'backupVaultDeployment' params: { // Required parameters name: 'dpbvwaf001' diff --git a/avm/res/databricks/access-connector/README.md b/avm/res/databricks/access-connector/README.md index 93eef78750..eab286a37c 100644 --- a/avm/res/databricks/access-connector/README.md +++ b/avm/res/databricks/access-connector/README.md @@ -42,7 +42,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module accessConnector 'br/public:avm/res/databricks/access-connector:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dacmin' + name: 'accessConnectorDeployment' params: { // Required parameters name: 'dacmin001' @@ -90,7 +90,7 @@ This instance deploys the module with most of its features enabled. ```bicep module accessConnector 'br/public:avm/res/databricks/access-connector:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dacmax' + name: 'accessConnectorDeployment' params: { // Required parameters name: 'dacmax001' @@ -210,7 +210,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module accessConnector 'br/public:avm/res/databricks/access-connector:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dacwaf' + name: 'accessConnectorDeployment' params: { // Required parameters name: 'dacwaf001' diff --git a/avm/res/databricks/workspace/README.md b/avm/res/databricks/workspace/README.md index 278713c94b..6fe8579a1a 100644 --- a/avm/res/databricks/workspace/README.md +++ b/avm/res/databricks/workspace/README.md @@ -46,7 +46,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module workspace 'br/public:avm/res/databricks/workspace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dwmin' + name: 'workspaceDeployment' params: { // Required parameters name: 'dwmin001' @@ -94,7 +94,7 @@ This instance deploys the module with most of its features enabled. ```bicep module workspace 'br/public:avm/res/databricks/workspace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dwmax' + name: 'workspaceDeployment' params: { // Required parameters name: 'dwmax001' @@ -372,7 +372,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module workspace 'br/public:avm/res/databricks/workspace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dwwaf' + name: 'workspaceDeployment' params: { // Required parameters name: 'dwwaf001' diff --git a/avm/res/db-for-my-sql/flexible-server/README.md b/avm/res/db-for-my-sql/flexible-server/README.md index cde312c15c..8855bd9946 100644 --- a/avm/res/db-for-my-sql/flexible-server/README.md +++ b/avm/res/db-for-my-sql/flexible-server/README.md @@ -47,7 +47,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dfmsfsmin' + name: 'flexibleServerDeployment' params: { // Required parameters name: 'dfmsfsmin001' @@ -111,7 +111,7 @@ This instance deploys the module with most of its features enabled. ```bicep module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dfmsmax' + name: 'flexibleServerDeployment' params: { // Required parameters name: 'dfmsmax001' @@ -395,7 +395,7 @@ This instance deploys the module with connectivity mode "Private Access". ```bicep module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dfmspvt' + name: 'flexibleServerDeployment' params: { // Required parameters name: 'dfmspvt001' @@ -531,7 +531,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dfmswaf' + name: 'flexibleServerDeployment' params: { // Required parameters name: 'dfmswaf001' 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 d112b86ec3..7dbf10b66b 100644 --- a/avm/res/db-for-postgre-sql/flexible-server/README.md +++ b/avm/res/db-for-postgre-sql/flexible-server/README.md @@ -49,7 +49,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module flexibleServer 'br/public:avm/res/db-for-postgre-sql/flexible-server:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dfpsfsmin' + name: 'flexibleServerDeployment' params: { // Required parameters name: 'dfpsfsmin001' @@ -113,7 +113,7 @@ This instance deploys the module using Customer-Managed-Keys using a User-Assign ```bicep module flexibleServer 'br/public:avm/res/db-for-postgre-sql/flexible-server:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dfpsfse' + name: 'flexibleServerDeployment' params: { // Required parameters name: 'dfpsfse001' @@ -201,7 +201,7 @@ This instance deploys the module with private access only. ```bicep module flexibleServer 'br/public:avm/res/db-for-postgre-sql/flexible-server:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dfpsfspvt' + name: 'flexibleServerDeployment' params: { // Required parameters name: 'dfpsfspvt001' @@ -403,7 +403,7 @@ This instance deploys the module with public access. ```bicep module flexibleServer 'br/public:avm/res/db-for-postgre-sql/flexible-server:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dfpsfsp' + name: 'flexibleServerDeployment' params: { // Required parameters name: 'dfpsfsp001' @@ -647,7 +647,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module flexibleServer 'br/public:avm/res/db-for-postgre-sql/flexible-server:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dfpsfswaf' + name: 'flexibleServerDeployment' params: { // Required parameters name: 'dfpsfswaf001' diff --git a/avm/res/desktop-virtualization/application-group/README.md b/avm/res/desktop-virtualization/application-group/README.md index 226afffc3b..d29b429e5d 100644 --- a/avm/res/desktop-virtualization/application-group/README.md +++ b/avm/res/desktop-virtualization/application-group/README.md @@ -44,7 +44,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module applicationGroup 'br/public:avm/res/desktop-virtualization/application-group:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dvagmin' + name: 'applicationGroupDeployment' params: { // Required parameters applicationGroupType: 'Desktop' @@ -100,7 +100,7 @@ This instance deploys the module with most of its features enabled. ```bicep module applicationGroup 'br/public:avm/res/desktop-virtualization/application-group:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dvagmax' + name: 'applicationGroupDeployment' params: { // Required parameters applicationGroupType: 'RemoteApp' @@ -286,7 +286,7 @@ This instance deploys the module in alignment with the best-practices of the Wel ```bicep module applicationGroup 'br/public:avm/res/desktop-virtualization/application-group:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dvagwaf' + name: 'applicationGroupDeployment' params: { // Required parameters applicationGroupType: 'Desktop' diff --git a/avm/res/desktop-virtualization/host-pool/README.md b/avm/res/desktop-virtualization/host-pool/README.md index c064356ace..62c54eae35 100644 --- a/avm/res/desktop-virtualization/host-pool/README.md +++ b/avm/res/desktop-virtualization/host-pool/README.md @@ -45,7 +45,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module hostPool 'br/public:avm/res/desktop-virtualization/host-pool:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dvhpmin' + name: 'hostPoolDeployment' params: { // Required parameters name: 'dvhpmin002' @@ -93,7 +93,7 @@ This instance deploys the module with most of its features enabled. ```bicep module hostPool 'br/public:avm/res/desktop-virtualization/host-pool:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dvhpmax' + name: 'hostPoolDeployment' params: { // Required parameters name: 'dvhpmax001' @@ -363,7 +363,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module hostPool 'br/public:avm/res/desktop-virtualization/host-pool:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dvhpwaf' + name: 'hostPoolDeployment' params: { // Required parameters name: 'dvhpwaf002' diff --git a/avm/res/desktop-virtualization/scaling-plan/README.md b/avm/res/desktop-virtualization/scaling-plan/README.md index 856c5bc093..929d4e7d14 100644 --- a/avm/res/desktop-virtualization/scaling-plan/README.md +++ b/avm/res/desktop-virtualization/scaling-plan/README.md @@ -43,7 +43,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module scalingPlan 'br/public:avm/res/desktop-virtualization/scaling-plan:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dvspmin' + name: 'scalingPlanDeployment' params: { // Required parameters name: 'dvspmin002' @@ -91,7 +91,7 @@ This instance deploys the module with most of its features enabled. ```bicep module scalingPlan 'br/public:avm/res/desktop-virtualization/scaling-plan:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dvspmax' + name: 'scalingPlanDeployment' params: { // Required parameters name: 'dvspmax002' @@ -467,7 +467,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module scalingPlan 'br/public:avm/res/desktop-virtualization/scaling-plan:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dvspwaf' + name: 'scalingPlanDeployment' params: { // Required parameters name: 'dvspwaf002' diff --git a/avm/res/desktop-virtualization/workspace/README.md b/avm/res/desktop-virtualization/workspace/README.md index f8592993aa..85cd414cf6 100644 --- a/avm/res/desktop-virtualization/workspace/README.md +++ b/avm/res/desktop-virtualization/workspace/README.md @@ -45,7 +45,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module workspace 'br/public:avm/res/desktop-virtualization/workspace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dvwsmin' + name: 'workspaceDeployment' params: { // Required parameters name: 'dvwsmin002' @@ -93,7 +93,7 @@ This instance deploys the module with most of its features enabled. ```bicep module workspace 'br/public:avm/res/desktop-virtualization/workspace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dvwsmax' + name: 'workspaceDeployment' params: { // Required parameters name: 'dvwsmax001' @@ -383,7 +383,7 @@ This instance deploys the module in alignment with the best-practices of the Wel ```bicep module workspace 'br/public:avm/res/desktop-virtualization/workspace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dvwswaf' + name: 'workspaceDeployment' params: { // Required parameters name: 'dvwswaf002' diff --git a/avm/res/dev-test-lab/lab/README.md b/avm/res/dev-test-lab/lab/README.md index 6e603a0de8..462e6836ac 100644 --- a/avm/res/dev-test-lab/lab/README.md +++ b/avm/res/dev-test-lab/lab/README.md @@ -48,7 +48,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module lab 'br/public:avm/res/dev-test-lab/lab:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dtllmin' + name: 'labDeployment' params: { // Required parameters name: 'dtllmin001' @@ -96,7 +96,7 @@ This instance deploys the module with most of its features enabled. ```bicep module lab 'br/public:avm/res/dev-test-lab/lab:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dtllmax' + name: 'labDeployment' params: { // Required parameters name: 'dtllmax001' @@ -654,7 +654,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module lab 'br/public:avm/res/dev-test-lab/lab:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-dtllwaf' + name: 'labDeployment' params: { // Required parameters name: 'dtllwaf001' diff --git a/avm/res/document-db/database-account/README.md b/avm/res/document-db/database-account/README.md index 5f13c53560..48ecea6820 100644 --- a/avm/res/document-db/database-account/README.md +++ b/avm/res/document-db/database-account/README.md @@ -63,7 +63,7 @@ This instance deploys the module with analytical storage enabled. ```bicep module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddaanl' + name: 'databaseAccountDeployment' params: { // Required parameters locations: [ @@ -143,7 +143,7 @@ This instance deploys the module disabling automatic failover. ```bicep module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddaauo' + name: 'databaseAccountDeployment' params: { // Required parameters locations: [ @@ -233,7 +233,7 @@ This instance deploys the module specifying a default consistency level. ```bicep module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddabco' + name: 'databaseAccountDeployment' params: { // Required parameters locations: [ @@ -321,7 +321,7 @@ This instance deploys the module enabling continous backups. ```bicep module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddacbc' + name: 'databaseAccountDeployment' params: { // Required parameters locations: [ @@ -405,7 +405,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddamin' + name: 'databaseAccountDeployment' params: { // Required parameters locations: [ @@ -469,7 +469,7 @@ This instance deploys the module disabling local authentication. ```bicep module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddadlo' + name: 'databaseAccountDeployment' params: { // Required parameters locations: [ @@ -549,7 +549,7 @@ This instance deploys the module with a Gremlin Database. ```bicep module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddagrm' + name: 'databaseAccountDeployment' params: { // Required parameters locations: [ @@ -817,7 +817,7 @@ This instance deploys the module with a Mongo Database. ```bicep module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddamng' + name: 'databaseAccountDeployment' params: { // Required parameters locations: [ @@ -1351,7 +1351,7 @@ This instance deploys the module enabling periodic backups. ```bicep module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddapbc' + name: 'databaseAccountDeployment' params: { // Required parameters locations: [ @@ -1443,7 +1443,7 @@ This instance deploys the module without a Database. ```bicep module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddapln' + name: 'databaseAccountDeployment' params: { // Required parameters locations: [ @@ -1595,7 +1595,7 @@ This instance deploys the module with a SQL Database. ```bicep module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddasql' + name: 'databaseAccountDeployment' params: { // Required parameters locations: [ @@ -2149,7 +2149,7 @@ This instance deploys the module with an assigned system assigned managed identi ```bicep module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddasmi' + name: 'databaseAccountDeployment' params: { // Required parameters locations: [ @@ -2221,7 +2221,7 @@ This instance deploys the module with an assigned user assigned managed identity ```bicep module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddaumi' + name: 'databaseAccountDeployment' params: { // Required parameters locations: [ @@ -2297,7 +2297,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddawaf' + name: 'databaseAccountDeployment' params: { // Required parameters locations: [ @@ -2507,7 +2507,7 @@ This instance deploys the module enabling multiple zone redundant in multiple re ```bicep module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: '${uniqueString(deployment().name, enforcedLocation)}-test-dddazr' + name: 'databaseAccountDeployment' params: { // Required parameters locations: [ diff --git a/avm/res/event-grid/domain/README.md b/avm/res/event-grid/domain/README.md index 14374d14a5..28e296172a 100644 --- a/avm/res/event-grid/domain/README.md +++ b/avm/res/event-grid/domain/README.md @@ -46,7 +46,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module domain 'br/public:avm/res/event-grid/domain:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-egdmin' + name: 'domainDeployment' params: { // Required parameters name: 'egdmin001' @@ -94,7 +94,7 @@ This instance deploys the module with most of its features enabled. ```bicep module domain 'br/public:avm/res/event-grid/domain:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-egdmax' + name: 'domainDeployment' params: { // Required parameters name: 'egdmax001' @@ -292,7 +292,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module domain 'br/public:avm/res/event-grid/domain:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-egdwaf' + name: 'domainDeployment' params: { // Required parameters name: 'egdwaf001' diff --git a/avm/res/event-grid/namespace/README.md b/avm/res/event-grid/namespace/README.md index 7ce215883e..45b78c23b6 100644 --- a/avm/res/event-grid/namespace/README.md +++ b/avm/res/event-grid/namespace/README.md @@ -54,7 +54,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module namespace 'br/public:avm/res/event-grid/namespace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-egnmin' + name: 'namespaceDeployment' params: { // Required parameters name: 'egnmin001' @@ -102,7 +102,7 @@ This instance deploys the module with most of its features enabled. ```bicep module namespace 'br/public:avm/res/event-grid/namespace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-egnmax' + name: 'namespaceDeployment' params: { // Required parameters name: 'egnmax001' @@ -508,7 +508,7 @@ This instance deploys the module as a MQTT Broker with routing to a topic within ```bicep module namespace 'br/public:avm/res/event-grid/namespace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-egnmqttct' + name: 'namespaceDeployment' params: { // Required parameters name: 'egnmqttct001' @@ -844,7 +844,7 @@ This instance deploys the module as a MQTT Broker with routing to a topic within ```bicep module namespace 'br/public:avm/res/event-grid/namespace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-egnmqttnt' + name: 'namespaceDeployment' params: { // Required parameters name: 'egnmqttnt001' @@ -1180,7 +1180,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module namespace 'br/public:avm/res/event-grid/namespace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-egnwaf' + name: 'namespaceDeployment' params: { // Required parameters name: 'egnwaf001' diff --git a/avm/res/event-grid/system-topic/README.md b/avm/res/event-grid/system-topic/README.md index fb69e0682d..d6294900e9 100644 --- a/avm/res/event-grid/system-topic/README.md +++ b/avm/res/event-grid/system-topic/README.md @@ -44,7 +44,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module systemTopic 'br/public:avm/res/event-grid/system-topic:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-egstmin' + name: 'systemTopicDeployment' params: { // Required parameters name: 'egstmin001' @@ -100,7 +100,7 @@ This instance deploys the module with most of its features enabled. ```bicep module systemTopic 'br/public:avm/res/event-grid/system-topic:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-egstmax' + name: 'systemTopicDeployment' params: { // Required parameters name: 'egstmax001' @@ -300,7 +300,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module systemTopic 'br/public:avm/res/event-grid/system-topic:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-egstwaf' + name: 'systemTopicDeployment' params: { // Required parameters name: 'egstwaf001' diff --git a/avm/res/event-grid/topic/README.md b/avm/res/event-grid/topic/README.md index 2126d9c209..33cdc4a048 100644 --- a/avm/res/event-grid/topic/README.md +++ b/avm/res/event-grid/topic/README.md @@ -46,7 +46,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module topic 'br/public:avm/res/event-grid/topic:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-egtmin' + name: 'topicDeployment' params: { // Required parameters name: 'egtmin001' @@ -94,7 +94,7 @@ This instance deploys the module with most of its features enabled. ```bicep module topic 'br/public:avm/res/event-grid/topic:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-egtmax' + name: 'topicDeployment' params: { // Required parameters name: 'egtmax001' @@ -356,7 +356,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module topic 'br/public:avm/res/event-grid/topic:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-egtwaf' + name: 'topicDeployment' params: { // Required parameters name: 'egtwaf001' diff --git a/avm/res/event-hub/namespace/README.md b/avm/res/event-hub/namespace/README.md index 679eb8dbc3..237e7d1941 100644 --- a/avm/res/event-hub/namespace/README.md +++ b/avm/res/event-hub/namespace/README.md @@ -52,7 +52,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module namespace 'br/public:avm/res/event-hub/namespace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ehnmin' + name: 'namespaceDeployment' params: { // Required parameters name: 'ehnmin001' @@ -100,7 +100,7 @@ This instance deploys the module using Customer-Managed-Keys using a User-Assign ```bicep module namespace 'br/public:avm/res/event-hub/namespace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ehnenc' + name: 'namespaceDeployment' params: { // Required parameters name: 'ehnenc001' @@ -186,7 +186,7 @@ This instance deploys the module with most of its features enabled. ```bicep module namespace 'br/public:avm/res/event-hub/namespace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ehnmax' + name: 'namespaceDeployment' params: { // Required parameters name: 'ehnmax001' @@ -604,7 +604,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module namespace 'br/public:avm/res/event-hub/namespace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ehnwaf' + name: 'namespaceDeployment' params: { // Required parameters name: 'ehnwaf001' diff --git a/avm/res/health-bot/health-bot/README.md b/avm/res/health-bot/health-bot/README.md index f0bb6b306d..8425995006 100644 --- a/avm/res/health-bot/health-bot/README.md +++ b/avm/res/health-bot/health-bot/README.md @@ -47,7 +47,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module healthBot 'br/public:avm/res/health-bot/health-bot:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-hbhbmin' + name: 'healthBotDeployment' params: { // Required parameters name: 'hbhbmin002' @@ -99,7 +99,7 @@ This instance deploys the module with most of its features enabled. ```bicep module healthBot 'br/public:avm/res/health-bot/health-bot:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-hbhbmax' + name: 'healthBotDeployment' params: { // Required parameters name: 'hbhbmax002' @@ -221,7 +221,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module healthBot 'br/public:avm/res/health-bot/health-bot:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-hbhbwaf' + name: 'healthBotDeployment' params: { // Required parameters name: 'hbhbwaf002' diff --git a/avm/res/insights/action-group/README.md b/avm/res/insights/action-group/README.md index 988ac3551b..fe40b8a7f0 100644 --- a/avm/res/insights/action-group/README.md +++ b/avm/res/insights/action-group/README.md @@ -41,7 +41,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module actionGroup 'br/public:avm/res/insights/action-group:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-iagmin' + name: 'actionGroupDeployment' params: { // Required parameters groupShortName: 'agiagmin001' @@ -93,7 +93,7 @@ This instance deploys the module with most of its features enabled. ```bicep module actionGroup 'br/public:avm/res/insights/action-group:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-iagmax' + name: 'actionGroupDeployment' params: { // Required parameters groupShortName: 'agiagmax001' @@ -235,7 +235,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module actionGroup 'br/public:avm/res/insights/action-group:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-iagwaf' + name: 'actionGroupDeployment' params: { // Required parameters groupShortName: 'agiagwaf001' diff --git a/avm/res/insights/activity-log-alert/README.md b/avm/res/insights/activity-log-alert/README.md index 305212ff6a..0917daf0a2 100644 --- a/avm/res/insights/activity-log-alert/README.md +++ b/avm/res/insights/activity-log-alert/README.md @@ -46,7 +46,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module activityLogAlert 'br/public:avm/res/insights/activity-log-alert:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ialamin' + name: 'activityLogAlertDeployment' params: { // Required parameters conditions: [ @@ -156,7 +156,7 @@ This instance deploys the module with most of its features enabled. ```bicep module activityLogAlert 'br/public:avm/res/insights/activity-log-alert:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ialamax' + name: 'activityLogAlertDeployment' params: { // Required parameters conditions: [ @@ -338,7 +338,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module activityLogAlert 'br/public:avm/res/insights/activity-log-alert:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ialawaf' + name: 'activityLogAlertDeployment' params: { // Required parameters conditions: [ diff --git a/avm/res/insights/component/README.md b/avm/res/insights/component/README.md index 7c9b4122d5..356dcd7811 100644 --- a/avm/res/insights/component/README.md +++ b/avm/res/insights/component/README.md @@ -43,7 +43,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module component 'br/public:avm/res/insights/component:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-icmin' + name: 'componentDeployment' params: { // Required parameters name: 'icmin001' @@ -95,7 +95,7 @@ This instance deploys the module with most of its features enabled. ```bicep module component 'br/public:avm/res/insights/component:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-icmax' + name: 'componentDeployment' params: { // Required parameters name: 'icmax001' @@ -241,7 +241,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module component 'br/public:avm/res/insights/component:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-icwaf' + name: 'componentDeployment' params: { // Required parameters name: 'icwaf001' diff --git a/avm/res/insights/data-collection-endpoint/README.md b/avm/res/insights/data-collection-endpoint/README.md index 6b912f0b7b..c4a647bdfb 100644 --- a/avm/res/insights/data-collection-endpoint/README.md +++ b/avm/res/insights/data-collection-endpoint/README.md @@ -42,7 +42,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module dataCollectionEndpoint 'br/public:avm/res/insights/data-collection-endpoint:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-idcemin' + name: 'dataCollectionEndpointDeployment' params: { // Required parameters name: 'idcemin001' @@ -90,7 +90,7 @@ This instance deploys the module with most of its features enabled. ```bicep module dataCollectionEndpoint 'br/public:avm/res/insights/data-collection-endpoint:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-idcemax' + name: 'dataCollectionEndpointDeployment' params: { // Required parameters name: 'idcemax001' @@ -204,7 +204,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module dataCollectionEndpoint 'br/public:avm/res/insights/data-collection-endpoint:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-idcewaf' + name: 'dataCollectionEndpointDeployment' params: { // Required parameters name: 'idcewaf001' diff --git a/avm/res/insights/data-collection-rule/README.md b/avm/res/insights/data-collection-rule/README.md index d9c06a97da..2cd6623d8e 100644 --- a/avm/res/insights/data-collection-rule/README.md +++ b/avm/res/insights/data-collection-rule/README.md @@ -47,7 +47,7 @@ This instance deploys the module to setup collection of custom logs and ingestio ```bicep module dataCollectionRule 'br/public:avm/res/insights/data-collection-rule:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-idcrcusadv' + name: 'dataCollectionRuleDeployment' params: { // Required parameters dataFlows: [ @@ -267,7 +267,7 @@ This instance deploys the module to setup collection of custom logs. ```bicep module dataCollectionRule 'br/public:avm/res/insights/data-collection-rule:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-idcrcusbas' + name: 'dataCollectionRuleDeployment' params: { // Required parameters dataFlows: [ @@ -455,7 +455,7 @@ This instance deploys the module to setup the collection of IIS logs. ```bicep module dataCollectionRule 'br/public:avm/res/insights/data-collection-rule:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-idcrcusiis' + name: 'dataCollectionRuleDeployment' params: { // Required parameters dataFlows: [ @@ -599,7 +599,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module dataCollectionRule 'br/public:avm/res/insights/data-collection-rule:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-idcrmin' + name: 'dataCollectionRuleDeployment' params: { // Required parameters dataFlows: [ @@ -733,7 +733,7 @@ This instance deploys the module to setup the collection of Linux-specific perfo ```bicep module dataCollectionRule 'br/public:avm/res/insights/data-collection-rule:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-idcrlin' + name: 'dataCollectionRuleDeployment' params: { // Required parameters dataFlows: [ @@ -1101,7 +1101,7 @@ This instance deploys the module with most of its features enabled. ```bicep module dataCollectionRule 'br/public:avm/res/insights/data-collection-rule:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-idcrmax' + name: 'dataCollectionRuleDeployment' params: { // Required parameters dataFlows: [ @@ -1335,7 +1335,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module dataCollectionRule 'br/public:avm/res/insights/data-collection-rule:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-idcrwaf' + name: 'dataCollectionRuleDeployment' params: { // Required parameters dataFlows: [ @@ -1611,7 +1611,7 @@ This instance deploys the module to setup the connection of Windows-specific per ```bicep module dataCollectionRule 'br/public:avm/res/insights/data-collection-rule:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-idcrwin' + name: 'dataCollectionRuleDeployment' params: { // Required parameters dataFlows: [ diff --git a/avm/res/insights/diagnostic-setting/README.md b/avm/res/insights/diagnostic-setting/README.md index 2b1b23c78b..94bbc70a30 100644 --- a/avm/res/insights/diagnostic-setting/README.md +++ b/avm/res/insights/diagnostic-setting/README.md @@ -40,7 +40,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module diagnosticSetting 'br/public:avm/res/insights/diagnostic-setting:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-idsmin' + name: 'diagnosticSettingDeployment' params: { location: '' name: 'idsmin001' @@ -88,7 +88,7 @@ This instance deploys the module with most of its features enabled. ```bicep module diagnosticSetting 'br/public:avm/res/insights/diagnostic-setting:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-idsmax' + name: 'diagnosticSettingDeployment' params: { eventHubAuthorizationRuleResourceId: '' eventHubName: '' @@ -160,7 +160,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module diagnosticSetting 'br/public:avm/res/insights/diagnostic-setting:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-idswaf' + name: 'diagnosticSettingDeployment' params: { eventHubAuthorizationRuleResourceId: '' eventHubName: '' diff --git a/avm/res/insights/metric-alert/README.md b/avm/res/insights/metric-alert/README.md index ab28f9a3d5..573b4301db 100644 --- a/avm/res/insights/metric-alert/README.md +++ b/avm/res/insights/metric-alert/README.md @@ -41,7 +41,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module metricAlert 'br/public:avm/res/insights/metric-alert:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-imamin' + name: 'metricAlertDeployment' params: { // Required parameters criterias: [ @@ -121,7 +121,7 @@ This instance deploys the module with most of its features enabled. ```bicep module metricAlert 'br/public:avm/res/insights/metric-alert:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-imamax' + name: 'metricAlertDeployment' params: { // Required parameters criterias: [ @@ -265,7 +265,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module metricAlert 'br/public:avm/res/insights/metric-alert:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-imawaf' + name: 'metricAlertDeployment' params: { // Required parameters criterias: [ diff --git a/avm/res/insights/private-link-scope/README.md b/avm/res/insights/private-link-scope/README.md index 0bdff8e591..3cc1fbd357 100644 --- a/avm/res/insights/private-link-scope/README.md +++ b/avm/res/insights/private-link-scope/README.md @@ -44,7 +44,8 @@ This instance deploys the module with the minimum set of required parameters.

via Bicep module ```bicep - name: '${uniqueString(deployment().name, resourceLocation)}-test-iplsmin' +module privateLinkScope 'br/public:avm/res/insights/private-link-scope:' = { + name: 'privateLinkScopeDeployment' params: { // Required parameters name: 'iplsmin001' @@ -91,7 +92,8 @@ This instance deploys the module with most of its features enabled. via Bicep module ```bicep - name: '${uniqueString(deployment().name, resourceLocation)}-test-iplsmax' +module privateLinkScope 'br/public:avm/res/insights/private-link-scope:' = { + name: 'privateLinkScopeDeployment' params: { // Required parameters name: 'iplsmax001' @@ -460,7 +462,8 @@ This instance deploys the module in alignment with the best-practices of the Azu via Bicep module ```bicep - name: '${uniqueString(deployment().name, resourceLocation)}-test-iplswaf' +module privateLinkScope 'br/public:avm/res/insights/private-link-scope:' = { + name: 'privateLinkScopeDeployment' params: { // Required parameters name: 'iplswaf001' diff --git a/avm/res/insights/scheduled-query-rule/README.md b/avm/res/insights/scheduled-query-rule/README.md index 64c355a7d2..f23d8999a0 100644 --- a/avm/res/insights/scheduled-query-rule/README.md +++ b/avm/res/insights/scheduled-query-rule/README.md @@ -46,7 +46,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module scheduledQueryRule 'br/public:avm/res/insights/scheduled-query-rule:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-isqrmin' + name: 'scheduledQueryRuleDeployment' params: { // Required parameters criterias: { @@ -166,7 +166,7 @@ This instance deploys the module with most of its features enabled. ```bicep module scheduledQueryRule 'br/public:avm/res/insights/scheduled-query-rule:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-isqrmax' + name: 'scheduledQueryRuleDeployment' params: { // Required parameters criterias: { @@ -350,7 +350,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module scheduledQueryRule 'br/public:avm/res/insights/scheduled-query-rule:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-isqrwaf' + name: 'scheduledQueryRuleDeployment' params: { // Required parameters criterias: { diff --git a/avm/res/insights/webtest/README.md b/avm/res/insights/webtest/README.md index 6f37502f31..7b9a2349a0 100644 --- a/avm/res/insights/webtest/README.md +++ b/avm/res/insights/webtest/README.md @@ -47,7 +47,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module webtest 'br/public:avm/res/insights/webtest:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-iwtmin' + name: 'webtestDeployment' params: { // Required parameters appInsightResourceId: '' @@ -113,7 +113,7 @@ This instance deploys the module with most of its features enabled. ```bicep module webtest 'br/public:avm/res/insights/webtest:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-iwtmax' + name: 'webtestDeployment' params: { // Required parameters appInsightResourceId: '' @@ -253,7 +253,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module webtest 'br/public:avm/res/insights/webtest:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-iwtwaf' + name: 'webtestDeployment' params: { // Required parameters appInsightResourceId: '' diff --git a/avm/res/key-vault/vault/README.md b/avm/res/key-vault/vault/README.md index 27a7344719..1782ef0a97 100644 --- a/avm/res/key-vault/vault/README.md +++ b/avm/res/key-vault/vault/README.md @@ -48,7 +48,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module vault 'br/public:avm/res/key-vault/vault:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-kvvmin' + name: 'vaultDeployment' params: { // Required parameters name: 'kvvmin002' @@ -100,7 +100,7 @@ This instance deploys the module with most of its features enabled. ```bicep module vault 'br/public:avm/res/key-vault/vault:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-kvvmax' + name: 'vaultDeployment' params: { // Required parameters name: 'kvvmax002' @@ -608,7 +608,7 @@ This instance deploys the module in alignment with the best-practices of the Wel ```bicep module vault 'br/public:avm/res/key-vault/vault:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-kvvwaf' + name: 'vaultDeployment' params: { // Required parameters name: 'kvvwaf002' diff --git a/avm/res/key-vault/vault/access-policy/main.json b/avm/res/key-vault/vault/access-policy/main.json index 567c4dc3c3..115b5ecb85 100644 --- a/avm/res/key-vault/vault/access-policy/main.json +++ b/avm/res/key-vault/vault/access-policy/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11791058225500616396" + "version": "0.26.54.24096", + "templateHash": "10878813547461142217" }, "name": "Key Vault Access Policies", "description": "This module deploys a Key Vault Access Policy.", diff --git a/avm/res/key-vault/vault/key/main.json b/avm/res/key-vault/vault/key/main.json index c24db6ea16..ada36d2d80 100644 --- a/avm/res/key-vault/vault/key/main.json +++ b/avm/res/key-vault/vault/key/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "9470802651294896537" + "version": "0.26.54.24096", + "templateHash": "5903918450419813264" }, "name": "Key Vault Keys", "description": "This module deploys a Key Vault Key.", diff --git a/avm/res/key-vault/vault/main.json b/avm/res/key-vault/vault/main.json index 40adf90666..c8128d3526 100644 --- a/avm/res/key-vault/vault/main.json +++ b/avm/res/key-vault/vault/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "5604749365634791124" + "version": "0.26.54.24096", + "templateHash": "7932330953480052072" }, "name": "Key Vaults", "description": "This module deploys a Key Vault.", @@ -882,8 +882,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11791058225500616396" + "version": "0.26.54.24096", + "templateHash": "10878813547461142217" }, "name": "Key Vault Access Policies", "description": "This module deploys a Key Vault Access Policy.", @@ -1151,8 +1151,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "13431676635055953332" + "version": "0.26.54.24096", + "templateHash": "1877278864243602204" }, "name": "Key Vault Secrets", "description": "This module deploys a Key Vault Secret.", @@ -1440,8 +1440,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "9470802651294896537" + "version": "0.26.54.24096", + "templateHash": "5903918450419813264" }, "name": "Key Vault Keys", "description": "This module deploys a Key Vault Key.", diff --git a/avm/res/key-vault/vault/secret/main.json b/avm/res/key-vault/vault/secret/main.json index 8f1a79c52a..8f7481aa2c 100644 --- a/avm/res/key-vault/vault/secret/main.json +++ b/avm/res/key-vault/vault/secret/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "13431676635055953332" + "version": "0.26.54.24096", + "templateHash": "1877278864243602204" }, "name": "Key Vault Secrets", "description": "This module deploys a Key Vault Secret.", diff --git a/avm/res/key-vault/vault/tests/e2e/defaults/main.test.bicep b/avm/res/key-vault/vault/tests/e2e/defaults/main.test.bicep index c735ade8c7..fe1f1e70c5 100644 --- a/avm/res/key-vault/vault/tests/e2e/defaults/main.test.bicep +++ b/avm/res/key-vault/vault/tests/e2e/defaults/main.test.bicep @@ -36,13 +36,15 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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}002' - location: resourceLocation - // Only for testing purposes - enablePurgeProtection: false +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + location: resourceLocation + // Only for testing purposes + enablePurgeProtection: false + } } -}] +] diff --git a/avm/res/key-vault/vault/tests/e2e/max/main.test.bicep b/avm/res/key-vault/vault/tests/e2e/max/main.test.bicep index e6cc12bba1..e76b304815 100644 --- a/avm/res/key-vault/vault/tests/e2e/max/main.test.bicep +++ b/avm/res/key-vault/vault/tests/e2e/max/main.test.bicep @@ -60,205 +60,147 @@ 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}002' - location: resourceLocation - accessPolicies: [ - { - objectId: nestedDependencies.outputs.managedIdentityPrincipalId - permissions: { - keys: [ - 'get' - 'list' - 'update' - ] - secrets: [ - 'all' - ] - } - tenantId: tenant().tenantId - } - { - objectId: nestedDependencies.outputs.managedIdentityPrincipalId - permissions: { - certificates: [ - 'backup' - 'create' - 'delete' - ] - secrets: [ - 'all' - ] - } - } - ] - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - logCategoriesAndGroups: [ - { - category: 'AzurePolicyEvaluationDetails' - } - { - category: 'AuditEvent' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - // Only for testing purposes - enablePurgeProtection: false - enableRbacAuthorization: false - keys: [ - { - attributesExp: 1725109032 - attributesNbf: 10000 - name: 'keyName' - 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' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + location: resourceLocation + accessPolicies: [ + { + objectId: nestedDependencies.outputs.managedIdentityPrincipalId + permissions: { + keys: [ + 'get' + 'list' + 'update' + ] + secrets: [ + 'all' + ] } - ] - rotationPolicy: { - attributes: { - expiryTime: 'P2Y' + tenantId: tenant().tenantId + } + { + objectId: nestedDependencies.outputs.managedIdentityPrincipalId + permissions: { + certificates: [ + 'backup' + 'create' + 'delete' + ] + secrets: [ + 'all' + ] } - lifetimeActions: [ + } + ] + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ { - trigger: { - timeBeforeExpiry: 'P2M' - } - action: { - type: 'Rotate' - } + category: 'AllMetrics' } + ] + logCategoriesAndGroups: [ { - trigger: { - timeBeforeExpiry: 'P30D' - } - action: { - type: 'Notify' - } + category: 'AzurePolicyEvaluationDetails' + } + { + category: 'AuditEvent' } ] - } - } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - networkAcls: { - bypass: 'AzureServices' - defaultAction: 'Deny' - ipRules: [ - { - value: '40.74.28.0/23' + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } ] - virtualNetworkRules: [ + // Only for testing purposes + enablePurgeProtection: false + enableRbacAuthorization: false + keys: [ { - id: nestedDependencies.outputs.subnetResourceId - ignoreMissingVnetServiceEndpoint: false + attributesExp: 1725109032 + attributesNbf: 10000 + name: 'keyName' + 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' + } + ] + rotationPolicy: { + attributes: { + expiryTime: 'P2Y' + } + lifetimeActions: [ + { + trigger: { + timeBeforeExpiry: 'P2M' + } + action: { + type: 'Rotate' + } + } + { + trigger: { + timeBeforeExpiry: 'P30D' + } + action: { + type: 'Notify' + } + } + ] + } } ] - } - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSResourceId - ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - ] - ipConfigurations: [ + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + networkAcls: { + bypass: 'AzureServices' + defaultAction: 'Deny' + ipRules: [ { - name: 'myIPconfig' - properties: { - groupId: 'vault' - memberName: 'default' - privateIPAddress: '10.0.0.10' - } + value: '40.74.28.0/23' } ] - customDnsConfigs: [ + virtualNetworkRules: [ { - fqdn: 'abc.keyvault.com' - ipAddresses: [ - '10.0.0.10' - ] + id: nestedDependencies.outputs.subnetResourceId + ignoreMissingVnetServiceEndpoint: false } ] } - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSResourceId - ] - subnetResourceId: 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' - } - ] - secrets: { - secureList: [ + privateEndpoints: [ { - attributesExp: 1702648632 - attributesNbf: 10000 - contentType: 'Something' - name: 'secretName' + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } roleAssignments: [ { roleDefinitionIdOrName: 'Owner' @@ -266,31 +208,103 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' principalType: 'ServicePrincipal' } { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) principalId: nestedDependencies.outputs.managedIdentityPrincipalId principalType: 'ServicePrincipal' } + ] + ipConfigurations: [ { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + name: 'myIPconfig' + properties: { + groupId: 'vault' + memberName: 'default' + privateIPAddress: '10.0.0.10' + } } ] - value: 'secretValue' + customDnsConfigs: [ + { + fqdn: 'abc.keyvault.com' + ipAddresses: [ + '10.0.0.10' + ] + } + ] + } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSResourceId + ] + subnetResourceId: 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' + } + ] + secrets: { + secureList: [ + { + attributesExp: 1702648632 + attributesNbf: 10000 + contentType: 'Something' + name: 'secretName' + 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' + } + ] + value: 'secretValue' + } + ] + } + softDeleteRetentionInDays: 7 + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } - softDeleteRetentionInDays: 7 - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] output resourceId string = testDeployment[0].outputs.resourceId diff --git a/avm/res/key-vault/vault/tests/e2e/waf-aligned/main.test.bicep b/avm/res/key-vault/vault/tests/e2e/waf-aligned/main.test.bicep index e0db10f622..f821d7012e 100644 --- a/avm/res/key-vault/vault/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/key-vault/vault/tests/e2e/waf-aligned/main.test.bicep @@ -60,91 +60,93 @@ 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}002' - location: resourceLocation - diagnosticSettings: [ - { - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - // Only for testing purposes - enablePurgeProtection: false - enableRbacAuthorization: true - keys: [ - { - attributesExp: 1725109032 - attributesNbf: 10000 - name: 'keyName' - rotationPolicy: { - attributes: { - expiryTime: 'P2Y' - } - lifetimeActions: [ - { - trigger: { - timeBeforeExpiry: 'P2M' - } - action: { - type: 'Rotate' - } +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + location: resourceLocation + diagnosticSettings: [ + { + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + // Only for testing purposes + enablePurgeProtection: false + enableRbacAuthorization: true + keys: [ + { + attributesExp: 1725109032 + attributesNbf: 10000 + name: 'keyName' + rotationPolicy: { + attributes: { + expiryTime: 'P2Y' } - { - trigger: { - timeBeforeExpiry: 'P30D' + lifetimeActions: [ + { + trigger: { + timeBeforeExpiry: 'P2M' + } + action: { + type: 'Rotate' + } } - action: { - type: 'Notify' + { + trigger: { + timeBeforeExpiry: 'P30D' + } + action: { + type: 'Notify' + } } - } - ] + ] + } + keySize: 4096 } - keySize: 4096 + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - networkAcls: { - bypass: 'AzureServices' - defaultAction: 'Deny' - } - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSResourceId - ] - service: 'vault' - subnetResourceId: nestedDependencies.outputs.subnetResourceId + networkAcls: { + bypass: 'AzureServices' + defaultAction: 'Deny' } - ] - secrets: { - secureList: [ + privateEndpoints: [ { - attributesExp: 1702648632 - attributesNbf: 10000 - contentType: 'Something' - name: 'secretName' - value: 'secretValue' + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSResourceId + ] + service: 'vault' + subnetResourceId: nestedDependencies.outputs.subnetResourceId } ] + secrets: { + secureList: [ + { + attributesExp: 1702648632 + attributesNbf: 10000 + contentType: 'Something' + name: 'secretName' + value: 'secretValue' + } + ] + } + softDeleteRetentionInDays: 7 + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } - softDeleteRetentionInDays: 7 - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/kubernetes-configuration/extension/README.md b/avm/res/kubernetes-configuration/extension/README.md index d97f6041c8..4a6a12ae57 100644 --- a/avm/res/kubernetes-configuration/extension/README.md +++ b/avm/res/kubernetes-configuration/extension/README.md @@ -42,7 +42,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module extension 'br/public:avm/res/kubernetes-configuration/extension:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-kcemin' + name: 'extensionDeployment' params: { // Required parameters clusterName: '' @@ -106,7 +106,7 @@ This instance deploys the module with most of its features enabled. ```bicep module extension 'br/public:avm/res/kubernetes-configuration/extension:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-kcemax' + name: 'extensionDeployment' params: { // Required parameters clusterName: '' @@ -137,6 +137,7 @@ module extension 'br/public:avm/res/kubernetes-configuration/extension: } } namespace: 'flux-system' + scope: 'cluster' suspend: false } ] @@ -198,6 +199,7 @@ module extension 'br/public:avm/res/kubernetes-configuration/extension: } }, "namespace": "flux-system", + "scope": "cluster", "suspend": false } ] @@ -232,7 +234,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module extension 'br/public:avm/res/kubernetes-configuration/extension:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-kcewaf' + name: 'extensionDeployment' params: { // Required parameters clusterName: '' @@ -263,6 +265,7 @@ module extension 'br/public:avm/res/kubernetes-configuration/extension: } } namespace: 'flux-system' + scope: 'cluster' suspend: false } ] @@ -324,6 +327,7 @@ module extension 'br/public:avm/res/kubernetes-configuration/extension: } }, "namespace": "flux-system", + "scope": "cluster", "suspend": false } ] diff --git a/avm/res/kubernetes-configuration/flux-configuration/README.md b/avm/res/kubernetes-configuration/flux-configuration/README.md index 50c7d39ba2..038b2387ec 100644 --- a/avm/res/kubernetes-configuration/flux-configuration/README.md +++ b/avm/res/kubernetes-configuration/flux-configuration/README.md @@ -41,7 +41,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module fluxConfiguration 'br/public:avm/res/kubernetes-configuration/flux-configuration:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-kcfcmin' + name: 'fluxConfigurationDeployment' params: { // Required parameters clusterName: '' @@ -52,6 +52,7 @@ module fluxConfiguration 'br/public:avm/res/kubernetes-configuration/flux-config } name: 'kcfcmin001' namespace: 'flux-system' + scope: 'cluster' sourceKind: 'GitRepository' // Non-required parameters gitRepository: { @@ -97,6 +98,9 @@ module fluxConfiguration 'br/public:avm/res/kubernetes-configuration/flux-config "namespace": { "value": "flux-system" }, + "scope": { + "value": "cluster" + }, "sourceKind": { "value": "GitRepository" }, @@ -133,7 +137,7 @@ This instance deploys the module with most of its features enabled. ```bicep module fluxConfiguration 'br/public:avm/res/kubernetes-configuration/flux-configuration:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-kcfcmax' + name: 'fluxConfigurationDeployment' params: { // Required parameters clusterName: '' @@ -155,6 +159,7 @@ module fluxConfiguration 'br/public:avm/res/kubernetes-configuration/flux-config } name: 'kcfcmax001' namespace: 'flux-system' + scope: 'cluster' sourceKind: 'GitRepository' // Non-required parameters gitRepository: { @@ -211,6 +216,9 @@ module fluxConfiguration 'br/public:avm/res/kubernetes-configuration/flux-config "namespace": { "value": "flux-system" }, + "scope": { + "value": "cluster" + }, "sourceKind": { "value": "GitRepository" }, @@ -247,7 +255,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module fluxConfiguration 'br/public:avm/res/kubernetes-configuration/flux-configuration:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-kcfcwaf' + name: 'fluxConfigurationDeployment' params: { // Required parameters clusterName: '' @@ -263,6 +271,7 @@ module fluxConfiguration 'br/public:avm/res/kubernetes-configuration/flux-config } name: 'kcfcwaf001' namespace: 'flux-system' + scope: 'cluster' sourceKind: 'GitRepository' // Non-required parameters gitRepository: { @@ -313,6 +322,9 @@ module fluxConfiguration 'br/public:avm/res/kubernetes-configuration/flux-config "namespace": { "value": "flux-system" }, + "scope": { + "value": "cluster" + }, "sourceKind": { "value": "GitRepository" }, diff --git a/avm/res/logic/workflow/README.md b/avm/res/logic/workflow/README.md index e9c5c824ef..fe42386b0e 100644 --- a/avm/res/logic/workflow/README.md +++ b/avm/res/logic/workflow/README.md @@ -44,7 +44,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module workflow 'br/public:avm/res/logic/workflow:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-lwmin' + name: 'workflowDeployment' params: { // Required parameters name: 'lwmin001' @@ -92,7 +92,7 @@ This instance deploys the module with most of its features enabled. ```bicep module workflow 'br/public:avm/res/logic/workflow:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-lwmax' + name: 'workflowDeployment' params: { // Required parameters name: 'lwmax001' @@ -306,7 +306,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module workflow 'br/public:avm/res/logic/workflow:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-lwwaf' + name: 'workflowDeployment' params: { // Required parameters name: 'lwwaf001' diff --git a/avm/res/machine-learning-services/workspace/README.md b/avm/res/machine-learning-services/workspace/README.md index 82719f70bd..dec8862463 100644 --- a/avm/res/machine-learning-services/workspace/README.md +++ b/avm/res/machine-learning-services/workspace/README.md @@ -53,7 +53,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module workspace 'br/public:avm/res/machine-learning-services/workspace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-mlswmin' + name: 'workspaceDeployment' params: { // Required parameters associatedApplicationInsightsResourceId: '' @@ -117,7 +117,7 @@ This instance deploys the module using Customer-Managed-Keys using a User-Assign ```bicep module workspace 'br/public:avm/res/machine-learning-services/workspace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-mlswecr' + name: 'workspaceDeployment' params: { // Required parameters associatedApplicationInsightsResourceId: '' @@ -211,7 +211,7 @@ This instance deploys the module with most of its features enabled. ```bicep module workspace 'br/public:avm/res/machine-learning-services/workspace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-mlswmax' + name: 'workspaceDeployment' params: { // Required parameters associatedApplicationInsightsResourceId: '' @@ -495,7 +495,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module workspace 'br/public:avm/res/machine-learning-services/workspace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-mlswwaf' + name: 'workspaceDeployment' params: { // Required parameters associatedApplicationInsightsResourceId: '' diff --git a/avm/res/maintenance/maintenance-configuration/README.md b/avm/res/maintenance/maintenance-configuration/README.md index 6d4e9519e5..777e0b0848 100644 --- a/avm/res/maintenance/maintenance-configuration/README.md +++ b/avm/res/maintenance/maintenance-configuration/README.md @@ -42,7 +42,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module maintenanceConfiguration 'br/public:avm/res/maintenance/maintenance-configuration:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-mmcmin' + name: 'maintenanceConfigurationDeployment' params: { // Required parameters name: 'mmcmin001' @@ -90,7 +90,7 @@ This instance deploys the module with most of its features enabled. ```bicep module maintenanceConfiguration 'br/public:avm/res/maintenance/maintenance-configuration:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-mmcmax' + name: 'maintenanceConfigurationDeployment' params: { // Required parameters name: 'mmcmax001' @@ -119,6 +119,7 @@ module maintenanceConfiguration 'br/public:avm/res/maintenance/maintenance-confi kind: 'CanNotDelete' name: 'myCustomLockName' } + maintenanceScope: 'InGuestPatch' maintenanceWindow: { duration: '03:00' expirationDateTime: '9999-12-31 23:59:59' @@ -203,6 +204,9 @@ module maintenanceConfiguration 'br/public:avm/res/maintenance/maintenance-confi "name": "myCustomLockName" } }, + "maintenanceScope": { + "value": "InGuestPatch" + }, "maintenanceWindow": { "value": { "duration": "03:00", @@ -262,7 +266,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module maintenanceConfiguration 'br/public:avm/res/maintenance/maintenance-configuration:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-mmcwaf' + name: 'maintenanceConfigurationDeployment' params: { // Required parameters name: 'mmcwaf001' @@ -287,6 +291,7 @@ module maintenanceConfiguration 'br/public:avm/res/maintenance/maintenance-confi } } location: '' + maintenanceScope: 'InGuestPatch' maintenanceWindow: { duration: '03:00' expirationDateTime: '9999-12-31 23:59:59' @@ -348,6 +353,9 @@ module maintenanceConfiguration 'br/public:avm/res/maintenance/maintenance-confi "location": { "value": "" }, + "maintenanceScope": { + "value": "InGuestPatch" + }, "maintenanceWindow": { "value": { "duration": "03:00", diff --git a/avm/res/managed-identity/user-assigned-identity/README.md b/avm/res/managed-identity/user-assigned-identity/README.md index ed5bf13e95..3dd61286fe 100644 --- a/avm/res/managed-identity/user-assigned-identity/README.md +++ b/avm/res/managed-identity/user-assigned-identity/README.md @@ -43,7 +43,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module userAssignedIdentity 'br/public:avm/res/managed-identity/user-assigned-identity:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-miuaimin' + name: 'userAssignedIdentityDeployment' params: { // Required parameters name: 'miuaimin001' @@ -91,7 +91,7 @@ This instance deploys the module with most of its features enabled. ```bicep module userAssignedIdentity 'br/public:avm/res/managed-identity/user-assigned-identity:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-miuaimax' + name: 'userAssignedIdentityDeployment' params: { // Required parameters name: 'miuaimax001' @@ -219,7 +219,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module userAssignedIdentity 'br/public:avm/res/managed-identity/user-assigned-identity:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-miuaiwaf' + name: 'userAssignedIdentityDeployment' params: { // Required parameters name: 'miuaiwaf001' diff --git a/avm/res/management/management-group/README.md b/avm/res/management/management-group/README.md index 7a1b340df3..44cbb9d919 100644 --- a/avm/res/management/management-group/README.md +++ b/avm/res/management/management-group/README.md @@ -45,7 +45,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module managementGroup 'br/public:avm/res/management/management-group:' = { - name: '${uniqueString(deployment().name)}-test-mmgmin' + name: 'managementGroupDeployment' params: { // Required parameters name: 'mmgmin001' @@ -93,7 +93,7 @@ This instance deploys the module with most of its features enabled. ```bicep module managementGroup 'br/public:avm/res/management/management-group:' = { - name: '${uniqueString(deployment().name)}-test-mmgmax' + name: 'managementGroupDeployment' params: { // Required parameters name: 'mmgmax001' @@ -149,7 +149,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module managementGroup 'br/public:avm/res/management/management-group:' = { - name: '${uniqueString(deployment().name)}-test-mmgwaf' + name: 'managementGroupDeployment' params: { // Required parameters name: 'mmgwaf001' diff --git a/avm/res/net-app/net-app-account/README.md b/avm/res/net-app/net-app-account/README.md index 8d7c9b5bd4..cab3531c89 100644 --- a/avm/res/net-app/net-app-account/README.md +++ b/avm/res/net-app/net-app-account/README.md @@ -17,9 +17,9 @@ This module deploys an Azure NetApp File. | :-- | :-- | | `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.NetApp/netAppAccounts` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/netAppAccounts) | -| `Microsoft.NetApp/netAppAccounts/capacityPools` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/netAppAccounts/capacityPools) | -| `Microsoft.NetApp/netAppAccounts/capacityPools/volumes` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/netAppAccounts/capacityPools/volumes) | +| `Microsoft.NetApp/netAppAccounts` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2022-11-01/netAppAccounts) | +| `Microsoft.NetApp/netAppAccounts/capacityPools` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2022-11-01/netAppAccounts/capacityPools) | +| `Microsoft.NetApp/netAppAccounts/capacityPools/volumes` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2022-11-01/netAppAccounts/capacityPools/volumes) | ## Usage examples @@ -45,7 +45,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nanaamin' + name: 'netAppAccountDeployment' params: { // Required parameters name: 'nanaamin001' @@ -93,7 +93,7 @@ This instance deploys the module with most of its features enabled. ```bicep module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nanaamax' + name: 'netAppAccountDeployment' params: { // Required parameters name: 'nanaamax001' @@ -355,7 +355,7 @@ This instance deploys the module with nfs31. ```bicep module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nanaanfs3' + name: 'netAppAccountDeployment' params: { // Required parameters name: 'nanaanfs3001' @@ -595,7 +595,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nanaawaf' + name: 'netAppAccountDeployment' params: { // Required parameters name: 'nanaawaf001' diff --git a/avm/res/network/application-security-group/README.md b/avm/res/network/application-security-group/README.md index b2131c1a04..78754f6fb4 100644 --- a/avm/res/network/application-security-group/README.md +++ b/avm/res/network/application-security-group/README.md @@ -42,7 +42,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module applicationSecurityGroup 'br/public:avm/res/network/application-security-group:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nasgmin' + name: 'applicationSecurityGroupDeployment' params: { // Required parameters name: 'nasgmin001' @@ -90,7 +90,7 @@ This instance deploys the module with most of its features enabled. ```bicep module applicationSecurityGroup 'br/public:avm/res/network/application-security-group:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nasgmax' + name: 'applicationSecurityGroupDeployment' params: { // Required parameters name: 'nasgmax001' @@ -196,7 +196,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module applicationSecurityGroup 'br/public:avm/res/network/application-security-group:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nasgwaf' + name: 'applicationSecurityGroupDeployment' params: { // Required parameters name: 'nasgwaf001' diff --git a/avm/res/network/azure-firewall/README.md b/avm/res/network/azure-firewall/README.md index a202e20ed1..8629811336 100644 --- a/avm/res/network/azure-firewall/README.md +++ b/avm/res/network/azure-firewall/README.md @@ -48,7 +48,7 @@ This instance deploys the module and attaches an existing public IP address. ```bicep module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nafaddpip' + name: 'azureFirewallDeployment' params: { // Required parameters name: 'nafaddpip001' @@ -140,7 +140,7 @@ This instance deploys the module and will create a public IP address. ```bicep module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nafcstpip' + name: 'azureFirewallDeployment' params: { // Required parameters name: 'nafcstpip001' @@ -250,7 +250,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nafmin' + name: 'azureFirewallDeployment' params: { // Required parameters name: 'nafmin001' @@ -302,7 +302,7 @@ This instance deploys the module a vWAN in a typical hub setting. ```bicep module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nafhubcom' + name: 'azureFirewallDeployment' params: { // Required parameters name: 'nafhubcom001' @@ -370,7 +370,7 @@ This instance deploys the module a vWAN minimum hub setting. ```bicep module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nafhubmin' + name: 'azureFirewallDeployment' params: { // Required parameters name: 'nafhubmin001' @@ -434,7 +434,7 @@ This instance deploys the module with most of its features enabled. ```bicep module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nafmax' + name: 'azureFirewallDeployment' params: { // Required parameters name: 'nafmax001' @@ -756,7 +756,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module azureFirewall 'br/public:avm/res/network/azure-firewall:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nafwaf' + name: 'azureFirewallDeployment' params: { // Required parameters name: 'nafwaf001' diff --git a/avm/res/network/bastion-host/README.md b/avm/res/network/bastion-host/README.md index 3f82a253e1..5b50061748 100644 --- a/avm/res/network/bastion-host/README.md +++ b/avm/res/network/bastion-host/README.md @@ -45,7 +45,7 @@ This instance does not require a pre-deployed public IP but includes its deploym ```bicep module bastionHost 'br/public:avm/res/network/bastion-host:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nbhctmpip' + name: 'bastionHostDeployment' params: { // Required parameters name: 'nbhctmpip001' @@ -175,7 +175,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module bastionHost 'br/public:avm/res/network/bastion-host:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nbhmin' + name: 'bastionHostDeployment' params: { // Required parameters name: 'nbhmin001' @@ -227,7 +227,7 @@ This instance deploys the module with most of its features enabled. ```bicep module bastionHost 'br/public:avm/res/network/bastion-host:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nbhmax' + name: 'bastionHostDeployment' params: { // Required parameters name: 'nbhmax001' @@ -385,7 +385,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module bastionHost 'br/public:avm/res/network/bastion-host:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nbhwaf' + name: 'bastionHostDeployment' params: { // Required parameters name: 'nbhwaf001' diff --git a/avm/res/network/connection/README.md b/avm/res/network/connection/README.md index cfca233145..918116f245 100644 --- a/avm/res/network/connection/README.md +++ b/avm/res/network/connection/README.md @@ -42,7 +42,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module connection 'br/public:avm/res/network/connection:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ncmin' + name: 'connectionDeployment' params: { // Required parameters name: 'ncmin001' @@ -114,7 +114,7 @@ This instance deploys the module with most of its features enabled. ```bicep module connection 'br/public:avm/res/network/connection:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ncmax' + name: 'connectionDeployment' params: { // Required parameters name: 'ncmax001' @@ -220,7 +220,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module connection 'br/public:avm/res/network/connection:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ncwaf' + name: 'connectionDeployment' params: { // Required parameters name: 'ncwaf001' diff --git a/avm/res/network/ddos-protection-plan/README.md b/avm/res/network/ddos-protection-plan/README.md index f41dd6567f..b51627b8cf 100644 --- a/avm/res/network/ddos-protection-plan/README.md +++ b/avm/res/network/ddos-protection-plan/README.md @@ -42,7 +42,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module ddosProtectionPlan 'br/public:avm/res/network/ddos-protection-plan:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ndppmin' + name: 'ddosProtectionPlanDeployment' params: { // Required parameters name: 'ndppmin001' @@ -90,7 +90,7 @@ This instance deploys the module with most of its features enabled. ```bicep module ddosProtectionPlan 'br/public:avm/res/network/ddos-protection-plan:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ndppmax' + name: 'ddosProtectionPlanDeployment' params: { // Required parameters name: 'ndppmax001' @@ -196,7 +196,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module ddosProtectionPlan 'br/public:avm/res/network/ddos-protection-plan:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ndppwaf' + name: 'ddosProtectionPlanDeployment' params: { // Required parameters name: 'ndppwaf001' diff --git a/avm/res/network/dns-forwarding-ruleset/README.md b/avm/res/network/dns-forwarding-ruleset/README.md index 3f77cb624b..0f68d737bc 100644 --- a/avm/res/network/dns-forwarding-ruleset/README.md +++ b/avm/res/network/dns-forwarding-ruleset/README.md @@ -44,7 +44,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module dnsForwardingRuleset 'br/public:avm/res/network/dns-forwarding-ruleset:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ndfrsmin' + name: 'dnsForwardingRulesetDeployment' params: { // Required parameters dnsForwardingRulesetOutboundEndpointResourceIds: [ @@ -100,7 +100,7 @@ This instance deploys the module with most of its features enabled. ```bicep module dnsForwardingRuleset 'br/public:avm/res/network/dns-forwarding-ruleset:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ndfrsmax' + name: 'dnsForwardingRulesetDeployment' params: { // Required parameters dnsForwardingRulesetOutboundEndpointResourceIds: [ @@ -250,7 +250,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module dnsForwardingRuleset 'br/public:avm/res/network/dns-forwarding-ruleset:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ndfrswaf' + name: 'dnsForwardingRulesetDeployment' params: { // Required parameters dnsForwardingRulesetOutboundEndpointResourceIds: [ diff --git a/avm/res/network/dns-resolver/README.md b/avm/res/network/dns-resolver/README.md index 69757ff677..eed91bd4a8 100644 --- a/avm/res/network/dns-resolver/README.md +++ b/avm/res/network/dns-resolver/README.md @@ -44,7 +44,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module dnsResolver 'br/public:avm/res/network/dns-resolver:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ndrmin' + name: 'dnsResolverDeployment' params: { // Required parameters name: 'ndrmin001' @@ -96,7 +96,7 @@ This instance deploys the module with most of its features enabled. ```bicep module dnsResolver 'br/public:avm/res/network/dns-resolver:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ndrmax' + name: 'dnsResolverDeployment' params: { // Required parameters name: 'ndrmax001' @@ -234,7 +234,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module dnsResolver 'br/public:avm/res/network/dns-resolver:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ndrwaf' + name: 'dnsResolverDeployment' params: { // Required parameters name: 'ndrwaf001' diff --git a/avm/res/network/dns-zone/README.md b/avm/res/network/dns-zone/README.md index 69d5d2b65d..695d6a0350 100644 --- a/avm/res/network/dns-zone/README.md +++ b/avm/res/network/dns-zone/README.md @@ -52,7 +52,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module dnsZone 'br/public:avm/res/network/dns-zone:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ndzmin' + name: 'dnsZoneDeployment' params: { // Required parameters name: 'ndzmin001.com' @@ -100,7 +100,7 @@ This instance deploys the module with most of its features enabled. ```bicep module dnsZone 'br/public:avm/res/network/dns-zone:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ndzmax' + name: 'dnsZoneDeployment' params: { // Required parameters name: 'ndzmax001.com' @@ -660,7 +660,7 @@ This instance deploys the module in alignment with the best-practices of the Wel ```bicep module dnsZone 'br/public:avm/res/network/dns-zone:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ndzwaf' + name: 'dnsZoneDeployment' params: { // Required parameters name: 'ndzwaf001.com' diff --git a/avm/res/network/express-route-circuit/README.md b/avm/res/network/express-route-circuit/README.md index 137836134f..2294f5b3f4 100644 --- a/avm/res/network/express-route-circuit/README.md +++ b/avm/res/network/express-route-circuit/README.md @@ -43,7 +43,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module expressRouteCircuit 'br/public:avm/res/network/express-route-circuit:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nercmin' + name: 'expressRouteCircuitDeployment' params: { // Required parameters bandwidthInMbps: 50 @@ -103,7 +103,7 @@ This instance deploys the module with most of its features enabled. ```bicep module expressRouteCircuit 'br/public:avm/res/network/express-route-circuit:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nercmax' + name: 'expressRouteCircuitDeployment' params: { // Required parameters bandwidthInMbps: 50 @@ -156,7 +156,6 @@ module expressRouteCircuit 'br/public:avm/res/network/express-route-circuit:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nercwaf' + name: 'expressRouteCircuitDeployment' params: { // Required parameters bandwidthInMbps: 50 diff --git a/avm/res/network/express-route-gateway/README.md b/avm/res/network/express-route-gateway/README.md index 8bf06769a7..f626ed4024 100644 --- a/avm/res/network/express-route-gateway/README.md +++ b/avm/res/network/express-route-gateway/README.md @@ -42,7 +42,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module expressRouteGateway 'br/public:avm/res/network/express-route-gateway:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nergmin' + name: 'expressRouteGatewayDeployment' params: { // Required parameters name: 'nergmin001' @@ -94,7 +94,7 @@ This instance deploys the module with most of its features enabled. ```bicep module expressRouteGateway 'br/public:avm/res/network/express-route-gateway:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nergmax' + name: 'expressRouteGatewayDeployment' params: { // Required parameters name: 'nergmax001' @@ -210,7 +210,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module expressRouteGateway 'br/public:avm/res/network/express-route-gateway:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nergwaf' + name: 'expressRouteGatewayDeployment' params: { // Required parameters name: 'nergwaf001' diff --git a/avm/res/network/firewall-policy/README.md b/avm/res/network/firewall-policy/README.md index 1141599ba5..b3c5f472f1 100644 --- a/avm/res/network/firewall-policy/README.md +++ b/avm/res/network/firewall-policy/README.md @@ -41,7 +41,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module firewallPolicy 'br/public:avm/res/network/firewall-policy:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nfpmin' + name: 'firewallPolicyDeployment' params: { // Required parameters name: 'nfpmin001' @@ -89,7 +89,7 @@ This instance deploys the module with most of its features enabled. ```bicep module firewallPolicy 'br/public:avm/res/network/firewall-policy:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nfpmax' + name: 'firewallPolicyDeployment' params: { // Required parameters name: 'nfpmax001' @@ -255,7 +255,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module firewallPolicy 'br/public:avm/res/network/firewall-policy:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nfpwaf' + name: 'firewallPolicyDeployment' params: { // Required parameters name: 'nfpwaf001' 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 a8cb404398..0efbac323a 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 @@ -42,7 +42,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module frontDoorWebApplicationFirewallPolicy 'br/public:avm/res/network/front-door-web-application-firewall-policy:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nagwafpmin' + name: 'frontDoorWebApplicationFirewallPolicyDeployment' params: { // Required parameters name: 'nagwafpmin001' @@ -90,7 +90,7 @@ This instance deploys the module with most of its features enabled. ```bicep module frontDoorWebApplicationFirewallPolicy 'br/public:avm/res/network/front-door-web-application-firewall-policy:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nagwafpmax' + name: 'frontDoorWebApplicationFirewallPolicyDeployment' params: { // Required parameters name: 'nagwafpmax001' @@ -330,7 +330,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module frontDoorWebApplicationFirewallPolicy 'br/public:avm/res/network/front-door-web-application-firewall-policy:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nagwafpwaf' + name: 'frontDoorWebApplicationFirewallPolicyDeployment' params: { // Required parameters name: 'nagwafpwaf001' diff --git a/avm/res/network/front-door/README.md b/avm/res/network/front-door/README.md index a6410897b1..3ca3f86595 100644 --- a/avm/res/network/front-door/README.md +++ b/avm/res/network/front-door/README.md @@ -43,7 +43,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module frontDoor 'br/public:avm/res/network/front-door:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nfdmin' + name: 'frontDoorDeployment' params: { // Required parameters backendPools: [ @@ -259,7 +259,7 @@ This instance deploys the module with most of its features enabled. ```bicep module frontDoor 'br/public:avm/res/network/front-door:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nfdmax' + name: 'frontDoorDeployment' params: { // Required parameters backendPools: [ @@ -595,7 +595,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module frontDoor 'br/public:avm/res/network/front-door:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nfdwaf' + name: 'frontDoorDeployment' params: { // Required parameters backendPools: [ diff --git a/avm/res/network/ip-group/README.md b/avm/res/network/ip-group/README.md index 42ce567b3d..e1c6409b70 100644 --- a/avm/res/network/ip-group/README.md +++ b/avm/res/network/ip-group/README.md @@ -42,7 +42,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module ipGroup 'br/public:avm/res/network/ip-group:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nigmin' + name: 'ipGroupDeployment' params: { // Required parameters name: 'nigmin001' @@ -90,7 +90,7 @@ This instance deploys the module with most of its features enabled. ```bicep module ipGroup 'br/public:avm/res/network/ip-group:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nigmax' + name: 'ipGroupDeployment' params: { // Required parameters name: 'nigmax001' @@ -206,7 +206,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module ipGroup 'br/public:avm/res/network/ip-group:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nigwaf' + name: 'ipGroupDeployment' params: { // Required parameters name: 'nigwaf001' diff --git a/avm/res/network/load-balancer/README.md b/avm/res/network/load-balancer/README.md index aee4173851..b3e5568a37 100644 --- a/avm/res/network/load-balancer/README.md +++ b/avm/res/network/load-balancer/README.md @@ -47,7 +47,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module loadBalancer 'br/public:avm/res/network/load-balancer:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nlbmin' + name: 'loadBalancerDeployment' params: { // Required parameters frontendIPConfigurations: [ @@ -117,7 +117,7 @@ This instance deploys the module with the minimum set of required parameters to ```bicep module loadBalancer 'br/public:avm/res/network/load-balancer:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nlbint' + name: 'loadBalancerDeployment' params: { // Required parameters frontendIPConfigurations: [ @@ -335,7 +335,7 @@ This instance deploys the module with most of its features enabled. ```bicep module loadBalancer 'br/public:avm/res/network/load-balancer:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nlbmax' + name: 'loadBalancerDeployment' params: { // Required parameters frontendIPConfigurations: [ @@ -643,7 +643,7 @@ This instance deploys the module in alignment with the best-practices of the Wel ```bicep module loadBalancer 'br/public:avm/res/network/load-balancer:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nlbwaf' + name: 'loadBalancerDeployment' params: { // Required parameters frontendIPConfigurations: [ diff --git a/avm/res/network/local-network-gateway/README.md b/avm/res/network/local-network-gateway/README.md index f913b29d05..e3892575f0 100644 --- a/avm/res/network/local-network-gateway/README.md +++ b/avm/res/network/local-network-gateway/README.md @@ -42,7 +42,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module localNetworkGateway 'br/public:avm/res/network/local-network-gateway:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nlngmin' + name: 'localNetworkGatewayDeployment' params: { // Required parameters localAddressPrefixes: [ @@ -102,7 +102,7 @@ This instance deploys the module with most of its features enabled. ```bicep module localNetworkGateway 'br/public:avm/res/network/local-network-gateway:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nlngmax' + name: 'localNetworkGatewayDeployment' params: { // Required parameters localAddressPrefixes: [ @@ -228,7 +228,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module localNetworkGateway 'br/public:avm/res/network/local-network-gateway:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nlngwaf' + name: 'localNetworkGatewayDeployment' params: { // Required parameters localAddressPrefixes: [ diff --git a/avm/res/network/nat-gateway/README.md b/avm/res/network/nat-gateway/README.md index e9464ccd9b..0f802ed8da 100644 --- a/avm/res/network/nat-gateway/README.md +++ b/avm/res/network/nat-gateway/README.md @@ -46,7 +46,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module natGateway 'br/public:avm/res/network/nat-gateway:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nngmin' + name: 'natGatewayDeployment' params: { // Required parameters name: 'nngmin001' @@ -94,7 +94,7 @@ This instance deploys the module with most of its features enabled. ```bicep module natGateway 'br/public:avm/res/network/nat-gateway:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nngmax' + name: 'natGatewayDeployment' params: { // Required parameters name: 'nngmax001' @@ -286,7 +286,7 @@ This example shows how you can provide a Public IP Prefix to the module, while a ```bicep module natGateway 'br/public:avm/res/network/nat-gateway:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nngcprx' + name: 'natGatewayDeployment' params: { // Required parameters name: 'nngcprx001' @@ -354,7 +354,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module natGateway 'br/public:avm/res/network/nat-gateway:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nngwaf' + name: 'natGatewayDeployment' params: { // Required parameters name: 'nngwaf001' diff --git a/avm/res/network/network-interface/README.md b/avm/res/network/network-interface/README.md index c16ceff283..1fbdd41fe9 100644 --- a/avm/res/network/network-interface/README.md +++ b/avm/res/network/network-interface/README.md @@ -43,7 +43,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module networkInterface 'br/public:avm/res/network/network-interface:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nnimin' + name: 'networkInterfaceDeployment' params: { // Required parameters ipConfigurations: [ @@ -105,7 +105,7 @@ This instance deploys the module with most of its features enabled. ```bicep module networkInterface 'br/public:avm/res/network/network-interface:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nnimax' + name: 'networkInterfaceDeployment' params: { // Required parameters ipConfigurations: [ @@ -281,7 +281,7 @@ This instance deploys the module in alignment with the best-practices of the Wel ```bicep module networkInterface 'br/public:avm/res/network/network-interface:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nniwaf' + name: 'networkInterfaceDeployment' params: { // Required parameters ipConfigurations: [ diff --git a/avm/res/network/network-manager/README.md b/avm/res/network/network-manager/README.md index bf2aee8932..448b6e5694 100644 --- a/avm/res/network/network-manager/README.md +++ b/avm/res/network/network-manager/README.md @@ -50,7 +50,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module networkManager 'br/public:avm/res/network/network-manager:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nnmmin' + name: 'networkManagerDeployment' params: { // Required parameters name: 'nnmmin001' @@ -118,7 +118,7 @@ This instance deploys the module with most of its features enabled. ```bicep module networkManager 'br/public:avm/res/network/network-manager:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nnmmax' + name: 'networkManagerDeployment' params: { // Required parameters name: '' @@ -588,7 +588,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module networkManager 'br/public:avm/res/network/network-manager:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nnmwaf' + name: 'networkManagerDeployment' params: { // Required parameters name: 'nnmwaf001' diff --git a/avm/res/network/network-security-group/README.md b/avm/res/network/network-security-group/README.md index 6a71380e4e..89644be609 100644 --- a/avm/res/network/network-security-group/README.md +++ b/avm/res/network/network-security-group/README.md @@ -44,7 +44,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module networkSecurityGroup 'br/public:avm/res/network/network-security-group:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nnsgmin' + name: 'networkSecurityGroupDeployment' params: { // Required parameters name: 'nnsgmin001' @@ -92,7 +92,7 @@ This instance deploys the module with most of its features enabled. ```bicep module networkSecurityGroup 'br/public:avm/res/network/network-security-group:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nnsgmax' + name: 'networkSecurityGroupDeployment' params: { // Required parameters name: 'nnsgmax001' @@ -348,7 +348,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module networkSecurityGroup 'br/public:avm/res/network/network-security-group:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nnsgwaf' + name: 'networkSecurityGroupDeployment' params: { // Required parameters name: 'nnsgwaf001' diff --git a/avm/res/network/private-dns-zone/README.md b/avm/res/network/private-dns-zone/README.md index 20447b9201..e78d7ad768 100644 --- a/avm/res/network/private-dns-zone/README.md +++ b/avm/res/network/private-dns-zone/README.md @@ -51,7 +51,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module privateDnsZone 'br/public:avm/res/network/private-dns-zone:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-npdzmin' + name: 'privateDnsZoneDeployment' params: { // Required parameters name: 'npdzmin001.com' @@ -99,7 +99,7 @@ This instance deploys the module with most of its features enabled. ```bicep module privateDnsZone 'br/public:avm/res/network/private-dns-zone:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-npdzmax' + name: 'privateDnsZoneDeployment' params: { // Required parameters name: 'npdzmax001.com' @@ -665,7 +665,7 @@ This instance deploys the module in alignment with the best-practices of the Wel ```bicep module privateDnsZone 'br/public:avm/res/network/private-dns-zone:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-npdzwaf' + name: 'privateDnsZoneDeployment' params: { // Required parameters name: 'npdzwaf001.com' diff --git a/avm/res/network/private-endpoint/README.md b/avm/res/network/private-endpoint/README.md index 37dc720a89..b5db7c46ce 100644 --- a/avm/res/network/private-endpoint/README.md +++ b/avm/res/network/private-endpoint/README.md @@ -43,7 +43,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module privateEndpoint 'br/public:avm/res/network/private-endpoint:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-npemin' + name: 'privateEndpointDeployment' params: { // Required parameters name: 'npemin001' @@ -159,7 +159,7 @@ This instance deploys the module with most of its features enabled. ```bicep module privateEndpoint 'br/public:avm/res/network/private-endpoint:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-npemax' + name: 'privateEndpointDeployment' params: { // Required parameters name: 'npemax001' @@ -363,7 +363,7 @@ This instance deploys the module in alignment with the best-practices of the Wel ```bicep module privateEndpoint 'br/public:avm/res/network/private-endpoint:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-npewaf' + name: 'privateEndpointDeployment' params: { // Required parameters name: 'npewaf001' diff --git a/avm/res/network/private-link-service/README.md b/avm/res/network/private-link-service/README.md index 192f187d73..2347f7d833 100644 --- a/avm/res/network/private-link-service/README.md +++ b/avm/res/network/private-link-service/README.md @@ -42,7 +42,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module privateLinkService 'br/public:avm/res/network/private-link-service:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nplsmin' + name: 'privateLinkServiceDeployment' params: { // Required parameters ipConfigurations: [ @@ -124,7 +124,7 @@ This instance deploys the module with most of its features enabled. ```bicep module privateLinkService 'br/public:avm/res/network/private-link-service:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nplsmax' + name: 'privateLinkServiceDeployment' params: { // Required parameters ipConfigurations: [ @@ -306,7 +306,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module privateLinkService 'br/public:avm/res/network/private-link-service:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nplswaf' + name: 'privateLinkServiceDeployment' params: { // Required parameters ipConfigurations: [ diff --git a/avm/res/network/public-ip-address/README.md b/avm/res/network/public-ip-address/README.md index f8f4322785..ffe18ec418 100644 --- a/avm/res/network/public-ip-address/README.md +++ b/avm/res/network/public-ip-address/README.md @@ -43,7 +43,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module publicIpAddress 'br/public:avm/res/network/public-ip-address:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-npiamin' + name: 'publicIpAddressDeployment' params: { // Required parameters name: 'npiamin001' @@ -91,7 +91,7 @@ This instance deploys the module with most of its features enabled. ```bicep module publicIpAddress 'br/public:avm/res/network/public-ip-address:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-npiamax' + name: 'publicIpAddressDeployment' params: { // Required parameters name: 'npiamax001' @@ -257,7 +257,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module publicIpAddress 'br/public:avm/res/network/public-ip-address:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-npiawaf' + name: 'publicIpAddressDeployment' params: { // Required parameters name: 'npiawaf001' diff --git a/avm/res/network/public-ip-prefix/README.md b/avm/res/network/public-ip-prefix/README.md index 09207d8853..b0f99688c6 100644 --- a/avm/res/network/public-ip-prefix/README.md +++ b/avm/res/network/public-ip-prefix/README.md @@ -42,7 +42,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module publicIpPrefix 'br/public:avm/res/network/public-ip-prefix:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-npipmin' + name: 'publicIpPrefixDeployment' params: { // Required parameters name: 'npipmin001' @@ -94,7 +94,7 @@ This instance deploys the module with most of its features enabled. ```bicep module publicIpPrefix 'br/public:avm/res/network/public-ip-prefix:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-npipmax' + name: 'publicIpPrefixDeployment' params: { // Required parameters name: 'npipmax001' @@ -204,7 +204,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module publicIpPrefix 'br/public:avm/res/network/public-ip-prefix:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-npipwaf' + name: 'publicIpPrefixDeployment' params: { // Required parameters name: 'npipwaf001' diff --git a/avm/res/network/route-table/README.md b/avm/res/network/route-table/README.md index 546e717454..753d31547a 100644 --- a/avm/res/network/route-table/README.md +++ b/avm/res/network/route-table/README.md @@ -42,7 +42,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module routeTable 'br/public:avm/res/network/route-table:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nrtmin' + name: 'routeTableDeployment' params: { // Required parameters name: 'nrtmin001' @@ -90,7 +90,7 @@ This instance deploys the module with most of its features enabled. ```bicep module routeTable 'br/public:avm/res/network/route-table:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nrtmax' + name: 'routeTableDeployment' params: { // Required parameters name: 'nrtmax001' @@ -218,7 +218,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module routeTable 'br/public:avm/res/network/route-table:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nrtwaf' + name: 'routeTableDeployment' params: { // Required parameters name: 'nrtwaf001' diff --git a/avm/res/network/trafficmanagerprofile/README.md b/avm/res/network/trafficmanagerprofile/README.md index 3a294c7455..4b87c3289c 100644 --- a/avm/res/network/trafficmanagerprofile/README.md +++ b/avm/res/network/trafficmanagerprofile/README.md @@ -43,7 +43,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module trafficmanagerprofile 'br/public:avm/res/network/trafficmanagerprofile:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ntmpmin' + name: 'trafficmanagerprofileDeployment' params: { // Required parameters name: 'ntmpmin001' @@ -91,7 +91,7 @@ This instance deploys the module with most of its features enabled. ```bicep module trafficmanagerprofile 'br/public:avm/res/network/trafficmanagerprofile:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ntmpmax' + name: 'trafficmanagerprofileDeployment' params: { // Required parameters name: 'ntmpmax001' @@ -231,7 +231,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module trafficmanagerprofile 'br/public:avm/res/network/trafficmanagerprofile:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ntmpwaf' + name: 'trafficmanagerprofileDeployment' params: { // Required parameters name: 'ntmpwaf001' diff --git a/avm/res/network/virtual-hub/README.md b/avm/res/network/virtual-hub/README.md index 9fa4017ba6..8ea957ca99 100644 --- a/avm/res/network/virtual-hub/README.md +++ b/avm/res/network/virtual-hub/README.md @@ -44,7 +44,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module virtualHub 'br/public:avm/res/network/virtual-hub:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nvhmin' + name: 'virtualHubDeployment' params: { // Required parameters addressPrefix: '10.0.0.0/16' @@ -100,7 +100,7 @@ This instance deploys the module with most of its features enabled. ```bicep module virtualHub 'br/public:avm/res/network/virtual-hub:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nvhmax' + name: 'virtualHubDeployment' params: { // Required parameters addressPrefix: '10.1.0.0/16' @@ -234,7 +234,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module virtualHub 'br/public:avm/res/network/virtual-hub:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nvhwaf' + name: 'virtualHubDeployment' params: { // Required parameters addressPrefix: '10.1.0.0/16' diff --git a/avm/res/network/virtual-network-gateway/README.md b/avm/res/network/virtual-network-gateway/README.md index bfaf37bcf3..a3cae95786 100644 --- a/avm/res/network/virtual-network-gateway/README.md +++ b/avm/res/network/virtual-network-gateway/README.md @@ -48,7 +48,7 @@ This instance deploys the module with the AAD set of required parameters. ```bicep module virtualNetworkGateway 'br/public:avm/res/network/virtual-network-gateway:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nvngavpn' + name: 'virtualNetworkGatewayDeployment' params: { // Required parameters gatewayType: 'Vpn' @@ -160,7 +160,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module virtualNetworkGateway 'br/public:avm/res/network/virtual-network-gateway:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nvgmin' + name: 'virtualNetworkGatewayDeployment' params: { // Required parameters gatewayType: 'Vpn' @@ -232,7 +232,7 @@ This instance deploys the module with the ExpressRoute set of required parameter ```bicep module virtualNetworkGateway 'br/public:avm/res/network/virtual-network-gateway:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nvger' + name: 'virtualNetworkGatewayDeployment' params: { // Required parameters gatewayType: 'ExpressRoute' @@ -316,7 +316,7 @@ This instance deploys the module with most of its features enabled. ```bicep module virtualNetworkGateway 'br/public:avm/res/network/virtual-network-gateway:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nvgmax' + name: 'virtualNetworkGatewayDeployment' params: { // Required parameters gatewayType: 'Vpn' @@ -586,7 +586,7 @@ This instance deploys the module with the VPN set of required parameters. ```bicep module virtualNetworkGateway 'br/public:avm/res/network/virtual-network-gateway:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nvgvpn' + name: 'virtualNetworkGatewayDeployment' params: { // Required parameters gatewayType: 'Vpn' @@ -698,7 +698,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module virtualNetworkGateway 'br/public:avm/res/network/virtual-network-gateway:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nvgmwaf' + name: 'virtualNetworkGatewayDeployment' params: { // Required parameters gatewayType: 'Vpn' diff --git a/avm/res/network/virtual-network/README.md b/avm/res/network/virtual-network/README.md index 8dd569aba2..87cb1ddedc 100644 --- a/avm/res/network/virtual-network/README.md +++ b/avm/res/network/virtual-network/README.md @@ -47,7 +47,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module virtualNetwork 'br/public:avm/res/network/virtual-network:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nvnmin' + name: 'virtualNetworkDeployment' params: { // Required parameters addressPrefixes: [ @@ -103,7 +103,7 @@ This instance deploys the module with most of its features enabled. ```bicep module virtualNetwork 'br/public:avm/res/network/virtual-network:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nvnmax' + name: 'virtualNetworkDeployment' params: { // Required parameters addressPrefixes: [ @@ -355,7 +355,7 @@ This instance deploys the module with both an inbound and outbound peering. ```bicep module virtualNetwork 'br/public:avm/res/network/virtual-network:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nvnpeer' + name: 'virtualNetworkDeployment' params: { // Required parameters addressPrefixes: [ @@ -483,7 +483,7 @@ This instance deploys the module in alignment with the best-practices of the Wel ```bicep module virtualNetwork 'br/public:avm/res/network/virtual-network:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nvnwaf' + name: 'virtualNetworkDeployment' params: { // Required parameters addressPrefixes: [ diff --git a/avm/res/network/virtual-wan/README.md b/avm/res/network/virtual-wan/README.md index 044630e644..0b34e1155b 100644 --- a/avm/res/network/virtual-wan/README.md +++ b/avm/res/network/virtual-wan/README.md @@ -42,7 +42,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module virtualWan 'br/public:avm/res/network/virtual-wan:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nvwmin' + name: 'virtualWanDeployment' params: { // Required parameters name: 'nvwmin001' @@ -90,7 +90,7 @@ This instance deploys the module with most of its features enabled. ```bicep module virtualWan 'br/public:avm/res/network/virtual-wan:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nvwmax' + name: 'virtualWanDeployment' params: { // Required parameters name: 'nvwmax001' @@ -212,7 +212,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module virtualWan 'br/public:avm/res/network/virtual-wan:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nvwwaf' + name: 'virtualWanDeployment' params: { // Required parameters name: 'nvwwaf001' diff --git a/avm/res/network/vpn-gateway/README.md b/avm/res/network/vpn-gateway/README.md index 714f323bab..0db0ca8bc2 100644 --- a/avm/res/network/vpn-gateway/README.md +++ b/avm/res/network/vpn-gateway/README.md @@ -44,7 +44,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module vpnGateway 'br/public:avm/res/network/vpn-gateway:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-vpngmin' + name: 'vpnGatewayDeployment' params: { // Required parameters name: 'vpngmin001' @@ -96,7 +96,7 @@ This instance deploys the module with most of its features enabled. ```bicep module vpnGateway 'br/public:avm/res/network/vpn-gateway:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-vpngmax' + name: 'vpnGatewayDeployment' params: { // Required parameters name: 'vpngmax001' @@ -246,7 +246,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module vpnGateway 'br/public:avm/res/network/vpn-gateway:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-vpngwaf' + name: 'vpnGatewayDeployment' params: { // Required parameters name: 'vpngwaf001' diff --git a/avm/res/network/vpn-site/README.md b/avm/res/network/vpn-site/README.md index 990c5b2f13..faa4df700b 100644 --- a/avm/res/network/vpn-site/README.md +++ b/avm/res/network/vpn-site/README.md @@ -43,7 +43,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module vpnSite 'br/public:avm/res/network/vpn-site:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nvsmin' + name: 'vpnSiteDeployment' params: { // Required parameters name: 'nvsmin' @@ -107,7 +107,7 @@ This instance deploys the module with most of its features enabled. ```bicep module vpnSite 'br/public:avm/res/network/vpn-site:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nvsmax' + name: 'vpnSiteDeployment' params: { // Required parameters name: 'nvsmax' @@ -303,7 +303,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module vpnSite 'br/public:avm/res/network/vpn-site:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-nvswaf' + name: 'vpnSiteDeployment' params: { // Required parameters name: 'nvswaf' diff --git a/avm/res/operational-insights/workspace/README.md b/avm/res/operational-insights/workspace/README.md index 89db6a899d..21b105fc0e 100644 --- a/avm/res/operational-insights/workspace/README.md +++ b/avm/res/operational-insights/workspace/README.md @@ -52,7 +52,7 @@ This instance deploys the module with advanced features like custom tables and d ```bicep module workspace 'br/public:avm/res/operational-insights/workspace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-oiwadv' + name: 'workspaceDeployment' params: { // Required parameters name: 'oiwadv001' @@ -666,7 +666,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module workspace 'br/public:avm/res/operational-insights/workspace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-oiwmin' + name: 'workspaceDeployment' params: { // Required parameters name: 'oiwmin001' @@ -714,7 +714,7 @@ This instance deploys the module with most of its features enabled. ```bicep module workspace 'br/public:avm/res/operational-insights/workspace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-oiwmax' + name: 'workspaceDeployment' params: { // Required parameters name: 'oiwmax001' @@ -1336,7 +1336,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module workspace 'br/public:avm/res/operational-insights/workspace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-oiwwaf' + name: 'workspaceDeployment' params: { // Required parameters name: 'oiwwaf001' diff --git a/avm/res/operations-management/solution/README.md b/avm/res/operations-management/solution/README.md index fa0f9fac57..715aa4ebca 100644 --- a/avm/res/operations-management/solution/README.md +++ b/avm/res/operations-management/solution/README.md @@ -41,7 +41,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module solution 'br/public:avm/res/operations-management/solution:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-omsmin' + name: 'solutionDeployment' params: { // Required parameters logAnalyticsWorkspaceName: '' @@ -93,7 +93,7 @@ This instance deploys the module with a Microsoft solution. ```bicep module solution 'br/public:avm/res/operations-management/solution:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-omsms' + name: 'solutionDeployment' params: { // Required parameters logAnalyticsWorkspaceName: '' @@ -153,7 +153,7 @@ This instance deploys the module with a third party (Non-Microsoft) solution. ```bicep module solution 'br/public:avm/res/operations-management/solution:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-omsnonms' + name: 'solutionDeployment' params: { // Required parameters logAnalyticsWorkspaceName: '' @@ -213,7 +213,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module solution 'br/public:avm/res/operations-management/solution:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-omswaf' + name: 'solutionDeployment' params: { // Required parameters logAnalyticsWorkspaceName: '' diff --git a/avm/res/power-bi-dedicated/capacity/README.md b/avm/res/power-bi-dedicated/capacity/README.md index e723c4b70a..778b42b06d 100644 --- a/avm/res/power-bi-dedicated/capacity/README.md +++ b/avm/res/power-bi-dedicated/capacity/README.md @@ -42,7 +42,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module capacity 'br/public:avm/res/power-bi-dedicated/capacity:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-pbdcapmin' + name: 'capacityDeployment' params: { // Required parameters members: [ @@ -106,7 +106,7 @@ This instance deploys the module with most of its features enabled. ```bicep module capacity 'br/public:avm/res/power-bi-dedicated/capacity:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-pbdcapmax' + name: 'capacityDeployment' params: { // Required parameters members: [ @@ -236,7 +236,7 @@ This instance deploys the module in alignment with the best-practices of the Wel ```bicep module capacity 'br/public:avm/res/power-bi-dedicated/capacity:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-pbdcapwaf' + name: 'capacityDeployment' params: { // Required parameters members: [ diff --git a/avm/res/purview/account/README.md b/avm/res/purview/account/README.md index 9d14e21bfb..0630647d57 100644 --- a/avm/res/purview/account/README.md +++ b/avm/res/purview/account/README.md @@ -50,7 +50,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module account 'br/public:avm/res/purview/account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-pvamin' + name: 'accountDeployment' params: { // Required parameters name: 'pvamin001' @@ -98,7 +98,7 @@ This instance deploys the module with most of its features enabled. ```bicep module account 'br/public:avm/res/purview/account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-pvamax' + name: 'accountDeployment' params: { // Required parameters name: 'pvamax001' @@ -428,7 +428,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module account 'br/public:avm/res/purview/account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-pvawaf' + name: 'accountDeployment' params: { // Required parameters name: 'pvawaf001' diff --git a/avm/res/resource-graph/query/README.md b/avm/res/resource-graph/query/README.md index 828aa6e04d..067f0bec33 100644 --- a/avm/res/resource-graph/query/README.md +++ b/avm/res/resource-graph/query/README.md @@ -42,7 +42,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module query 'br/public:avm/res/resource-graph/query:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-rdsmin' + name: 'queryDeployment' params: { // Required parameters name: 'rdsmin001' @@ -94,7 +94,7 @@ This instance deploys the module with most of its features enabled. ```bicep module query 'br/public:avm/res/resource-graph/query:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-rdsmax' + name: 'queryDeployment' params: { // Required parameters name: 'rdsmax001' @@ -206,7 +206,7 @@ This instance deploys the module in alignment with the best-practices of the Wel ```bicep module query 'br/public:avm/res/resource-graph/query:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-rdswaf' + name: 'queryDeployment' params: { // Required parameters name: 'rdswaf001' diff --git a/avm/res/resources/deployment-script/README.md b/avm/res/resources/deployment-script/README.md index 81dcf69cdf..1432d407c5 100644 --- a/avm/res/resources/deployment-script/README.md +++ b/avm/res/resources/deployment-script/README.md @@ -45,7 +45,7 @@ This instance deploys the module with an Azure CLI script. ```bicep module deploymentScript 'br/public:avm/res/resources/deployment-script:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-rdscli' + name: 'deploymentScriptDeployment' params: { // Required parameters kind: 'AzureCLI' @@ -143,7 +143,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module deploymentScript 'br/public:avm/res/resources/deployment-script:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-rdsmin' + name: 'deploymentScriptDeployment' params: { // Required parameters kind: 'AzurePowerShell' @@ -219,7 +219,7 @@ This instance deploys the module with most of its features enabled. ```bicep module deploymentScript 'br/public:avm/res/resources/deployment-script:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-rdsmax' + name: 'deploymentScriptDeployment' params: { // Required parameters kind: 'AzureCLI' @@ -401,7 +401,7 @@ This instance deploys the module with access to a private network. ```bicep module deploymentScript 'br/public:avm/res/resources/deployment-script:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-rdsnet' + name: 'deploymentScriptDeployment' params: { // Required parameters kind: 'AzureCLI' @@ -501,7 +501,7 @@ This instance deploys the module with an Azure PowerShell script. ```bicep module deploymentScript 'br/public:avm/res/resources/deployment-script:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-rdsps' + name: 'deploymentScriptDeployment' params: { // Required parameters kind: 'AzurePowerShell' @@ -585,7 +585,7 @@ This instance deploys the module in alignment with the best-practices of the Wel ```bicep module deploymentScript 'br/public:avm/res/resources/deployment-script:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-rdswaf' + name: 'deploymentScriptDeployment' params: { // Required parameters kind: 'AzureCLI' diff --git a/avm/res/resources/resource-group/README.md b/avm/res/resources/resource-group/README.md index dc1ba768a0..abbd41ebde 100644 --- a/avm/res/resources/resource-group/README.md +++ b/avm/res/resources/resource-group/README.md @@ -42,7 +42,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module resourceGroup 'br/public:avm/res/resources/resource-group:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-rrgmin' + name: 'resourceGroupDeployment' params: { // Required parameters name: 'avm-resources.resourcegroups-rrgmin-rg' @@ -90,7 +90,7 @@ This instance deploys the module with most of its features enabled. ```bicep module resourceGroup 'br/public:avm/res/resources/resource-group:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-rrgmax' + name: 'resourceGroupDeployment' params: { // Required parameters name: 'avm-resources.resourcegroups-rrgmax-rg' @@ -196,7 +196,7 @@ This instance deploys the module in alignment with the best-practices of the Wel ```bicep module resourceGroup 'br/public:avm/res/resources/resource-group:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-rrgwaf' + name: 'resourceGroupDeployment' params: { // Required parameters name: 'avm-resources.resourcegroups-rrgwaf-rg' diff --git a/avm/res/search/search-service/README.md b/avm/res/search/search-service/README.md index 2f113159ab..03ae42de32 100644 --- a/avm/res/search/search-service/README.md +++ b/avm/res/search/search-service/README.md @@ -47,7 +47,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module searchService 'br/public:avm/res/search/search-service:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-sssmin' + name: 'searchServiceDeployment' params: { // Required parameters name: 'sssmin001' @@ -95,7 +95,7 @@ This instance deploys the module with most of its features enabled. ```bicep module searchService 'br/public:avm/res/search/search-service:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-sssmax' + name: 'searchServiceDeployment' params: { // Required parameters name: 'sssmax001' @@ -301,7 +301,7 @@ This instance deploys the module with private endpoints. ```bicep module searchService 'br/public:avm/res/search/search-service:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ssspe' + name: 'searchServiceDeployment' params: { // Required parameters name: 'ssspe001' @@ -437,7 +437,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module searchService 'br/public:avm/res/search/search-service:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ssswaf' + name: 'searchServiceDeployment' params: { // Required parameters name: 'ssswaf001' diff --git a/avm/res/service-bus/namespace/README.md b/avm/res/service-bus/namespace/README.md index 8a3c9269d6..0e6355952f 100644 --- a/avm/res/service-bus/namespace/README.md +++ b/avm/res/service-bus/namespace/README.md @@ -55,7 +55,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module namespace 'br/public:avm/res/service-bus/namespace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-sbnmin' + name: 'namespaceDeployment' params: { // Required parameters name: 'sbnmin001' @@ -111,7 +111,7 @@ This instance deploys the module with features enabled for CMK encryption. ```bicep module namespace 'br/public:avm/res/service-bus/namespace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-sbnencr' + name: 'namespaceDeployment' params: { // Required parameters name: 'sbnencr001' @@ -195,7 +195,7 @@ This instance deploys the module with most of its features enabled. ```bicep module namespace 'br/public:avm/res/service-bus/namespace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-sbnmax' + name: 'namespaceDeployment' params: { // Required parameters name: 'sbnmax001' @@ -653,7 +653,7 @@ This instance deploys the module in alignment with the best-practices of the Wel ```bicep module namespace 'br/public:avm/res/service-bus/namespace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-sbnwaf' + name: 'namespaceDeployment' params: { // Required parameters name: 'sbnwaf001' diff --git a/avm/res/signal-r-service/signal-r/README.md b/avm/res/signal-r-service/signal-r/README.md index 4e9d91e25e..e01d1d7045 100644 --- a/avm/res/signal-r-service/signal-r/README.md +++ b/avm/res/signal-r-service/signal-r/README.md @@ -49,7 +49,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module signalR 'br/public:avm/res/signal-r-service/signal-r:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-srsdrmin' + name: 'signalRDeployment' params: { // Required parameters name: 'srsdrmin-001' @@ -97,7 +97,7 @@ This instance deploys the module with most of its features enabled. ```bicep module signalR 'br/public:avm/res/signal-r-service/signal-r:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-srssrmax' + name: 'signalRDeployment' params: { // Required parameters name: 'srssrmax-001' @@ -317,7 +317,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module signalR 'br/public:avm/res/signal-r-service/signal-r:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-srssrwaf' + name: 'signalRDeployment' params: { // Required parameters name: 'srssrwaf-001' 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 32fc5e052b..e50d13a31b 100644 --- a/avm/res/signal-r-service/web-pub-sub/README.md +++ b/avm/res/signal-r-service/web-pub-sub/README.md @@ -49,7 +49,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module webPubSub 'br/public:avm/res/signal-r-service/web-pub-sub:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-srswpsmin' + name: 'webPubSubDeployment' params: { // Required parameters name: 'srswpsmin-001' @@ -97,7 +97,7 @@ This instance deploys the module with most of its features enabled. ```bicep module webPubSub 'br/public:avm/res/signal-r-service/web-pub-sub:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-srswpsmax' + name: 'webPubSubDeployment' params: { // Required parameters name: 'srswpsmax-001' @@ -323,7 +323,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module webPubSub 'br/public:avm/res/signal-r-service/web-pub-sub:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-srswpswaf' + name: 'webPubSubDeployment' params: { // Required parameters name: 'srswpswaf-001' diff --git a/avm/res/sql/server/README.md b/avm/res/sql/server/README.md index 57de0cac75..362b3c8403 100644 --- a/avm/res/sql/server/README.md +++ b/avm/res/sql/server/README.md @@ -59,7 +59,7 @@ This instance deploys the module with a Microsoft Entra ID identity as SQL admin ```bicep module server 'br/public:avm/res/sql/server:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-sqlsadmin' + name: 'serverDeployment' params: { // Required parameters name: 'sqlsadmin' @@ -121,7 +121,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module server 'br/public:avm/res/sql/server:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ssmin' + name: 'serverDeployment' params: { // Required parameters name: 'ssmin001' @@ -177,7 +177,7 @@ This instance deploys the module with most of its features enabled. ```bicep module server 'br/public:avm/res/sql/server:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-sqlsmax' + name: 'serverDeployment' params: { // Required parameters name: 'sqlsmax' @@ -521,7 +521,7 @@ This instance deploys the module with a secondary database. ```bicep module server 'br/public:avm/res/sql/server:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-sqlsec' + name: 'serverDeployment' params: { // Required parameters name: 'sqlsec-sec' @@ -611,7 +611,7 @@ This instance deploys the module with a vulnerability assessment. ```bicep module server 'br/public:avm/res/sql/server:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-sqlsvln' + name: 'serverDeployment' params: { // Required parameters name: 'sqlsvln' @@ -739,7 +739,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module server 'br/public:avm/res/sql/server:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-sqlswaf' + name: 'serverDeployment' params: { // Required parameters name: 'sqlswaf' diff --git a/avm/res/storage/storage-account/README.md b/avm/res/storage/storage-account/README.md index 120deb76dc..4bdbae8b8e 100644 --- a/avm/res/storage/storage-account/README.md +++ b/avm/res/storage/storage-account/README.md @@ -63,7 +63,7 @@ This instance deploys the module as a Blob Storage account. ```bicep module storageAccount 'br/public:avm/res/storage/storage-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ssablob' + name: 'storageAccountDeployment' params: { // Required parameters name: 'ssablob001' @@ -119,7 +119,7 @@ This instance deploys the module as a Premium Block Blob Storage account. ```bicep module storageAccount 'br/public:avm/res/storage/storage-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ssablock' + name: 'storageAccountDeployment' params: { // Required parameters name: 'ssablock001' @@ -175,7 +175,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module storageAccount 'br/public:avm/res/storage/storage-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ssamin' + name: 'storageAccountDeployment' params: { // Required parameters name: 'ssamin001' @@ -223,7 +223,7 @@ This instance deploys the module with most of its features enabled. ```bicep module storageAccount 'br/public:avm/res/storage/storage-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ssamax' + name: 'storageAccountDeployment' params: { // Required parameters name: 'ssamax001' @@ -1089,7 +1089,7 @@ This instance deploys the module with a NFS File Share. ```bicep module storageAccount 'br/public:avm/res/storage/storage-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ssanfs' + name: 'storageAccountDeployment' params: { // Required parameters name: 'ssanfs001' @@ -1163,7 +1163,7 @@ This instance deploys the module using Customer-Managed-Keys using a System-Assi ```bicep module storageAccount 'br/public:avm/res/storage/storage-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ssasacr' + name: 'storageAccountDeployment' params: { // Required parameters name: '' @@ -1267,7 +1267,7 @@ This instance deploys the module using Customer-Managed-Keys using a User-Assign ```bicep module storageAccount 'br/public:avm/res/storage/storage-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ssauacr' + name: 'storageAccountDeployment' params: { // Required parameters name: 'ssauacr001' @@ -1387,7 +1387,7 @@ This instance deploys the module as Storage Account version 1. ```bicep module storageAccount 'br/public:avm/res/storage/storage-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ssav1' + name: 'storageAccountDeployment' params: { // Required parameters name: 'ssav1001' @@ -1439,7 +1439,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module storageAccount 'br/public:avm/res/storage/storage-account:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-ssawaf' + name: 'storageAccountDeployment' params: { // Required parameters name: 'ssawaf001' diff --git a/avm/res/synapse/private-link-hub/README.md b/avm/res/synapse/private-link-hub/README.md index 4299c4f1aa..d5d10a28d7 100644 --- a/avm/res/synapse/private-link-hub/README.md +++ b/avm/res/synapse/private-link-hub/README.md @@ -49,7 +49,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module privateLinkHub 'br/public:avm/res/synapse/private-link-hub:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-splhmin' + name: 'privateLinkHubDeployment' params: { // Required parameters name: 'splhmin001' @@ -97,7 +97,7 @@ This instance deploys the module with most of its features enabled. ```bicep module privateLinkHub 'br/public:avm/res/synapse/private-link-hub:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-splhmax' + name: 'privateLinkHubDeployment' params: { // Required parameters name: 'splhmax001' @@ -233,7 +233,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module privateLinkHub 'br/public:avm/res/synapse/private-link-hub:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-splhwaf' + name: 'privateLinkHubDeployment' params: { // Required parameters name: 'splhwaf001' diff --git a/avm/res/synapse/workspace/README.md b/avm/res/synapse/workspace/README.md index 79a2bd33e4..91a6b56496 100644 --- a/avm/res/synapse/workspace/README.md +++ b/avm/res/synapse/workspace/README.md @@ -56,7 +56,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module workspace 'br/public:avm/res/synapse/workspace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-swmin' + name: 'workspaceDeployment' params: { // Required parameters defaultDataLakeStorageAccountResourceId: '' @@ -116,7 +116,7 @@ This instance deploys the module using Customer-Managed-Keys using a System-Assi ```bicep module workspace 'br/public:avm/res/synapse/workspace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-swensa' + name: 'workspaceDeployment' params: { // Required parameters defaultDataLakeStorageAccountResourceId: '' @@ -190,7 +190,7 @@ This instance deploys the module using Customer-Managed-Keys using a User-Assign ```bicep module workspace 'br/public:avm/res/synapse/workspace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-swenua' + name: 'workspaceDeployment' params: { // Required parameters defaultDataLakeStorageAccountResourceId: '' @@ -262,7 +262,7 @@ This instance deploys the module using a managed Vnet. ```bicep module workspace 'br/public:avm/res/synapse/workspace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-swmanv' + name: 'workspaceDeployment' params: { // Required parameters defaultDataLakeStorageAccountResourceId: '' @@ -338,7 +338,7 @@ This instance deploys the module with most of its features enabled. ```bicep module workspace 'br/public:avm/res/synapse/workspace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-swmax' + name: 'workspaceDeployment' params: { // Required parameters defaultDataLakeStorageAccountResourceId: '' @@ -596,7 +596,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module workspace 'br/public:avm/res/synapse/workspace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-swwaf' + name: 'workspaceDeployment' params: { // Required parameters defaultDataLakeStorageAccountResourceId: '' diff --git a/avm/res/virtual-machine-images/image-template/README.md b/avm/res/virtual-machine-images/image-template/README.md index 18c11c37ec..e370d6fdae 100644 --- a/avm/res/virtual-machine-images/image-template/README.md +++ b/avm/res/virtual-machine-images/image-template/README.md @@ -43,7 +43,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module imageTemplate 'br/public:avm/res/virtual-machine-images/image-template:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-vmiitmin' + name: 'imageTemplateDeployment' params: { // Required parameters customizationSteps: [ @@ -147,7 +147,7 @@ This instance deploys the module with most of its features enabled. ```bicep module imageTemplate 'br/public:avm/res/virtual-machine-images/image-template:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-vmiitmax' + name: 'imageTemplateDeployment' params: { // Required parameters customizationSteps: [ @@ -389,7 +389,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module imageTemplate 'br/public:avm/res/virtual-machine-images/image-template:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-vmiitwaf' + name: 'imageTemplateDeployment' params: { // Required parameters customizationSteps: [ diff --git a/avm/res/web/serverfarm/README.md b/avm/res/web/serverfarm/README.md index 1cf7bf6af8..7788f77636 100644 --- a/avm/res/web/serverfarm/README.md +++ b/avm/res/web/serverfarm/README.md @@ -43,7 +43,7 @@ This instance deploys the module with a base set of parameters. Note it does inc ```bicep module serverfarm 'br/public:avm/res/web/serverfarm:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-wsfmin' + name: 'serverfarmDeployment' params: { // Required parameters name: 'wsfmin001' @@ -107,7 +107,7 @@ This instance deploys the module with most of its features enabled. ```bicep module serverfarm 'br/public:avm/res/web/serverfarm:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-wsfmax' + name: 'serverfarmDeployment' params: { // Required parameters name: 'wsfmax001' @@ -271,7 +271,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module serverfarm 'br/public:avm/res/web/serverfarm:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-wsfwaf' + name: 'serverfarmDeployment' params: { // Required parameters name: 'wsfwaf001' diff --git a/avm/res/web/site/README.md b/avm/res/web/site/README.md index 65ab42e075..150a304f80 100644 --- a/avm/res/web/site/README.md +++ b/avm/res/web/site/README.md @@ -57,7 +57,7 @@ This instance deploys the module as Function App with the minimum set of require ```bicep module site 'br/public:avm/res/web/site:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-wsfamin' + name: 'siteDeployment' params: { // Required parameters kind: 'functionapp' @@ -121,7 +121,7 @@ This instance deploys the module as Function App with most of its features enabl ```bicep module site 'br/public:avm/res/web/site:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-wsfamax' + name: 'siteDeployment' params: { // Required parameters kind: 'functionapp' @@ -509,7 +509,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module site 'br/public:avm/res/web/site:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-wswaf' + name: 'siteDeployment' params: { // Required parameters kind: 'app' @@ -651,7 +651,7 @@ This instance deploys the module as Web App with the minimum set of required par ```bicep module site 'br/public:avm/res/web/site:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-wswamin' + name: 'siteDeployment' params: { // Required parameters kind: 'app' @@ -718,7 +718,7 @@ This instance deploys the module as Web App with most of its features enabled. ```bicep module site 'br/public:avm/res/web/site:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-wswamax' + name: 'siteDeployment' params: { // Required parameters kind: 'app' diff --git a/avm/res/web/static-site/README.md b/avm/res/web/static-site/README.md index a0460e02f2..e27a78f15b 100644 --- a/avm/res/web/static-site/README.md +++ b/avm/res/web/static-site/README.md @@ -47,7 +47,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module staticSite 'br/public:avm/res/web/static-site:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-wssmin' + name: 'staticSiteDeployment' params: { // Required parameters name: 'wssmin001' @@ -95,7 +95,7 @@ This instance deploys the module with most of its features enabled. ```bicep module staticSite 'br/public:avm/res/web/static-site:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-wssmax' + name: 'staticSiteDeployment' params: { // Required parameters name: 'wssmax001' @@ -299,7 +299,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module staticSite 'br/public:avm/res/web/static-site:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-wsswaf' + name: 'staticSiteDeployment' params: { // Required parameters name: 'wsswaf001' diff --git a/avm/utilities/pipelines/sharedScripts/Set-ModuleReadMe.ps1 b/avm/utilities/pipelines/sharedScripts/Set-ModuleReadMe.ps1 index 5f50885f05..fc28f922c3 100644 --- a/avm/utilities/pipelines/sharedScripts/Set-ModuleReadMe.ps1 +++ b/avm/utilities/pipelines/sharedScripts/Set-ModuleReadMe.ps1 @@ -973,23 +973,54 @@ function ConvertTo-FormattedJSONParameterObject { $isLineWithReferenceInLineKey = ($line -split ':')[0].Trim() -like '*.*' $isLineWithStringValue = $lineValue -match '".+"' # e.g. "value" - $isLineWithFunction = $lineValue -match "^['|`"]{1}.*\$\{.+['|`"]{1}$|^['|`"]{0}[a-zA-Z\(]+\(.+" # e.g. (split(resourceGroupResources.outputs.recoveryServicesVaultResourceId, "/"))[4] or '${last(...)}' or last() or "test${environment()}" + $isLineWithStringNestedFunction = $lineValue -match "^['|`"]{1}.*\$\{.+['|`"]{1}$|^['|`"]{0}[a-zA-Z\(]+\(.+" # e.g. (split(resourceGroupResources.outputs.recoveryServicesVaultResourceId, "/"))[4] or '${last(...)}' or last() or "test${environment()}" $isLineWithPlainValue = $lineValue -match '^\w+$' # e.g. adminPassword: password $isLineWithPrimitiveValue = $lineValue -match '^\s*true|false|[0-9]+$' # e.g. isSecure: true - # Combined checks - # In case of an output reference like '"virtualWanId": resourceGroupResources.outputs.virtualWWANResourceId' we'll only show "" (but NOT e.g. 'reference': {}) - $isLineWithObjectPropertyReference = -not $isLineWithEmptyObjectValue -and -not $isLineWithStringValue -and $isLineWithObjectPropertyReferenceValue - # In case of a parameter/variable reference like 'adminPassword: password' we'll only show "" (but NOT e.g. enableMe: true) - $isLineWithParameterOrVariableReferenceValue = $isLineWithPlainValue -and -not $isLineWithPrimitiveValue - # In case of any contained line like ''${resourceGroupResources.outputs.managedIdentityResourceId}': {}' we'll only show "managedIdentityResourceId: {}" - $isLineWithObjectReferenceKeyAndEmptyObjectValue = $isLineWithEmptyObjectValue -and $isLineWithReferenceInLineKey - # In case of any contained function like '"backupVaultResourceGroup": (split(resourceGroupResources.outputs.recoveryServicesVaultResourceId, "/"))[4]' we'll only show "" + # Special case: Multi-line function + $isLineWithMultilineFunction = $lineValue -match '[a-zA-Z]+\s*\([^\)]*\){0}\s*$' # e.g. roleDefinitionIdOrName: subscriptionResourceId( \n 'Microsoft.Authorization/roleDefinitions', \n 'acdd72a7-3385-48ef-bd42-f606fba81ae7' \n ) + if ($isLineWithMultilineFunction) { + # Search leading indent so that we can use it to identify at which line the function ends + $indent = ([regex]::Match($paramInJSONFormatArray[$index], '^(\s+)')).Captures.Groups[1].Value.Length - if ($isLineWithObjectPropertyReference -or $isLineWithFunction -or $isLineWithParameterOrVariableReferenceValue) { + $functionStartIndex = $index + $functionEndIndex = $functionStartIndex + do { + $functionEndIndex++ + } while ($paramInJSONFormatArray[$functionEndIndex] -match "^\s{$($indent+1),}" -and $functionEndIndex -lt $paramInJSONFormatArray.Count) + + if ($functionEndIndex -eq $paramInJSONFormatArray.Count) { + throw "End index of a multi-line function block for test file [$CurrentFilePath] not found." + } + + # Overwrite the first line with a default value (i.e., "property": "") $line = '{0}: "<{1}>"' -f ($line -split ':')[0], ([regex]::Match(($line -split ':')[0], '"(.+)"')).Captures.Groups[1].Value - } elseif ($isLineWithObjectReferenceKeyAndEmptyObjectValue) { - $line = '"<{0}>": {1}' -f (($line -split ':')[0] -split '\.')[-1].TrimEnd('}"'), $lineValue + + $linesOfFunction = $functionEndIndex - $functionStartIndex + + # Nullify all but first line + for ($functionIndex = 1; $functionIndex -le $linesOfFunction; $functionIndex++) { + $functionLineIndex = $index + $functionIndex + $paramInJSONFormatArray[$functionLineIndex] = $null + } + + # Increase index to skip the function lines + $index += $indexToIncrease + } else { + # Combined checks + # In case of an output reference like '"virtualWanId": resourceGroupResources.outputs.virtualWWANResourceId' we'll only show "" (but NOT e.g. 'reference': {}) + $isLineWithObjectPropertyReference = -not $isLineWithEmptyObjectValue -and -not $isLineWithStringValue -and $isLineWithObjectPropertyReferenceValue + # In case of a parameter/variable reference like 'adminPassword: password' we'll only show "" (but NOT e.g. enableMe: true) + $isLineWithParameterOrVariableReferenceValue = $isLineWithPlainValue -and -not $isLineWithPrimitiveValue + # In case of any contained line like ''${resourceGroupResources.outputs.managedIdentityResourceId}': {}' we'll only show "managedIdentityResourceId: {}" + $isLineWithObjectReferenceKeyAndEmptyObjectValue = $isLineWithEmptyObjectValue -and $isLineWithReferenceInLineKey + # In case of any contained function like '"backupVaultResourceGroup": (split(resourceGroupResources.outputs.recoveryServicesVaultResourceId, "/"))[4]' we'll only show "" + + if ($isLineWithObjectPropertyReference -or $isLineWithStringNestedFunction -or $isLineWithParameterOrVariableReferenceValue) { + $line = '{0}: "<{1}>"' -f ($line -split ':')[0], ([regex]::Match(($line -split ':')[0], '"(.+)"')).Captures.Groups[1].Value + } elseif ($isLineWithObjectReferenceKeyAndEmptyObjectValue) { + $line = '"<{0}>": {1}' -f (($line -split ':')[0] -split '\.')[-1].TrimEnd('}"'), $lineValue + } } } else { if ($line -notlike '*"*"*' -and $line -like '*.*') { @@ -1001,11 +1032,13 @@ function ConvertTo-FormattedJSONParameterObject { } } - $paramInJSONFormatArray[$index] = $line } - # [2.6] Syntax: Add comma everywhere unless: + # [2.6] Remove empty lines + $paramInJSONFormatArray = $paramInJSONFormatArray | Where-Object { $_ } + + # [2.7] Syntax: Add comma everywhere unless: # - the current line has an opening 'object: {' or 'array: [' character # - the line after the current line has a closing 'object: {' or 'array: [' character # - it's the last closing bracket @@ -1016,7 +1049,7 @@ function ConvertTo-FormattedJSONParameterObject { $paramInJSONFormatArray[$index] = '{0},' -f $paramInJSONFormatArray[$index].Trim() } - # [2.7] Format the final JSON string to an object to enable processing + # [2.8] Format the final JSON string to an object to enable processing try { $paramInJsonFormatObject = $paramInJSONFormatArray | Out-String | ConvertFrom-Json -AsHashtable -Depth 99 -ErrorAction 'Stop' } catch { @@ -1301,43 +1334,60 @@ function Set-UsageExamplesSection { $bicepTestEndIndex = $bicepTestStartIndex do { $bicepTestEndIndex++ - } while ($rawContentArray[$bicepTestEndIndex] -notin @('}', '}]')) - - $rawBicepExample = $rawContentArray[$bicepTestStartIndex..$bicepTestEndIndex] + } while ($rawContentArray[$bicepTestEndIndex] -notin @('}', '}]', ']') -and $bicepTestEndIndex -lt $rawContentArray.Count) - if ($rawBicepExample[-1] -eq '}]') { - $rawBicepExample[-1] = '}' + if ($bicepTestEndIndex -eq $rawContentArray.Count) { + throw "End index of test block for test file [$testFilePath] not found." } - # [2/6] Replace placeholders - $serviceShort = ([regex]::Match($rawContent, "(?m)^param serviceShort string = '(.+)'\s*$")).Captures.Groups[1].Value - - $rawBicepExampleString = ($rawBicepExample | Out-String) - $rawBicepExampleString = $rawBicepExampleString -replace '\$\{serviceShort\}', $serviceShort - $rawBicepExampleString = $rawBicepExampleString -replace '\$\{namePrefix\}[-|\.|_]?', '' # Replacing with empty to not expose prefix and avoid potential deployment conflicts - $rawBicepExampleString = $rawBicepExampleString -replace '(?m):\s*location\s*$', ': ''''' - $rawBicepExampleString = $rawBicepExampleString -replace '-\$\{iteration\}', '' - - # [3/6] Format header, remove scope property & any empty line - $rawBicepExample = $rawBicepExampleString -split '\n' - $rawBicepExample[0] = "module $moduleNameCamelCase 'br/public:$($brLink):$($targetVersion)' = {" - $rawBicepExample = $rawBicepExample | Where-Object { $_ -notmatch 'scope: *' } | Where-Object { -not [String]::IsNullOrEmpty($_) } - # [4/6] Extract param block - $rawBicepExampleArray = $rawBicepExample -split '\n' - $moduleDeploymentPropertyIndent = ([regex]::Match($rawBicepExampleArray[1], '^(\s+).*')).Captures.Groups[1].Value.Length - $paramsStartIndex = ($rawBicepExampleArray | Select-String ("^[\s]{$moduleDeploymentPropertyIndent}params:[\s]*\{") | ForEach-Object { $_.LineNumber - 1 })[0] + 1 - if ($rawBicepExampleArray[$paramsStartIndex].Trim() -ne '}') { - # Handle case where param block is empty - $paramsEndIndex = ($rawBicepExampleArray[($paramsStartIndex + 1)..($rawBicepExampleArray.Count)] | Select-String "^[\s]{$moduleDeploymentPropertyIndent}\}" | ForEach-Object { $_.LineNumber - 1 })[0] + $paramsStartIndex - $paramBlock = ($rawBicepExampleArray[$paramsStartIndex..$paramsEndIndex] | Out-String).TrimEnd() + $rawBicepExample = $rawContentArray[$bicepTestStartIndex..$bicepTestEndIndex] + + if (-not ($rawBicepExample | Select-String ("\s+params:.*"))) { + # Handle case where params are not provided + $paramsBlockArray = @() } else { - $paramBlock = '' - $paramsEndIndex = $paramsStartIndex + # Extract params block out of the Bicep example + $paramsStartIndex = ($rawBicepExample | Select-String ("\s+params:.*") | ForEach-Object { $_.LineNumber - 1 })[0] + $paramsIndent = ($rawBicepExample[$paramsStartIndex] | Select-String '(\s+).*').Matches.Groups[1].Length + + + # Handle case where params are empty + if ($rawBicepExample[$paramsStartIndex] -match '^.*params:\s*\{\s*\}\s*$') { + $paramsBlockArray = @() + } else { + # Handle case where params are provided + $paramsEndIndex = $paramsStartIndex + do { + $paramsEndIndex++ + } while ($rawBicepExample[$paramsEndIndex] -notMatch "^\s{$paramsIndent}\}" -and + $rawBicepExample[$paramsEndIndex] -notMatch "^\s{$paramsIndent}\}\]" -and + $rawBicepExample[$paramsEndIndex] -notMatch "^\s{$paramsIndent}\]" -and + $paramsEndIndex -lt $rawBicepExample.Count) + + if ($paramsEndIndex -eq $rawBicepExample.Count) { + throw "End index of 'params' block for test file [$testFilePath] not found." + } + + $paramsBlock = $rawBicepExample[($paramsStartIndex + 1) .. ($paramsEndIndex - 1)] + $paramsBlockArray = $paramsBlock -replace "^\s{$paramsIndent}" # Remove excess leading spaces + + # [2/6] Replace placeholders + $serviceShort = ([regex]::Match($rawContent, "(?m)^param serviceShort string = '(.+)'\s*$")).Captures.Groups[1].Value + + $paramsBlockString = ($paramsBlockArray | Out-String) + $paramsBlockString = $paramsBlockString -replace '\$\{serviceShort\}', $serviceShort + $paramsBlockString = $paramsBlockString -replace '\$\{namePrefix\}[-|\.|_]?', '' # Replacing with empty to not expose prefix and avoid potential deployment conflicts + $paramsBlockString = $paramsBlockString -replace '(?m):\s*location\s*$', ': ''''' + + # [3/6] Format header, remove scope property & any empty line + $paramsBlockArray = $paramsBlockString -split '\n' | Where-Object { -not [String]::IsNullOrEmpty($_) } + $paramsBlockArray = $paramsBlockArray | ForEach-Object { " $_" } + } } # [5/6] Convert Bicep parameter block to JSON parameter block to enable processing $conversionInputObject = @{ - BicepParamBlock = $paramBlock + BicepParamBlock = ($paramsBlockArray | Out-String).TrimEnd() CurrentFilePath = $testFilePath } $paramsInJSONFormat = ConvertTo-FormattedJSONParameterObject @conversionInputObject @@ -1354,26 +1404,14 @@ function Set-UsageExamplesSection { # --------------------- # if ($addBicep) { - if ([String]::IsNullOrEmpty($paramBlock)) { - # Handle case where param block is empty - $formattedBicepExample = $rawBicepExample[0..($paramsStartIndex - 1)] + $rawBicepExample[($paramsEndIndex)..($rawBicepExample.Count)] - } else { - $formattedBicepExample = $rawBicepExample[0..($paramsStartIndex - 1)] + ($bicepExample -split '\n') + $rawBicepExample[($paramsEndIndex + 1)..($rawBicepExample.Count)] - } - - # Remove any dependsOn as it it test specific - if ($detected = ($formattedBicepExample | Select-String "^\s{$moduleDeploymentPropertyIndent}dependsOn:\s*\[\s*$" | ForEach-Object { $_.LineNumber - 1 })) { - $dependsOnStartIndex = $detected[0] - - # Find out where the 'dependsOn' ends - $dependsOnEndIndex = $dependsOnStartIndex - do { - $dependsOnEndIndex++ - } while ($formattedBicepExample[$dependsOnEndIndex] -notmatch '^\s*\]\s*$') - - # Cut the 'dependsOn' block out - $formattedBicepExample = $formattedBicepExample[0..($dependsOnStartIndex - 1)] + $formattedBicepExample[($dependsOnEndIndex + 1)..($formattedBicepExample.Count)] - } + $formattedBicepExample = @( + "module $moduleNameCamelCase 'br/public:$($brLink):$($targetVersion)' = {", + " name: '$($moduleNameCamelCase)Deployment'" + " params: {" + ) + $bicepExample + + @( ' }', + '}' + ) # Build result $testFilesContent += @( @@ -1687,7 +1725,7 @@ function Set-ModuleReadMe { . (Join-Path $PSScriptRoot 'helper' 'Get-SpecsAlignedResourceName.ps1') . (Join-Path $PSScriptRoot 'helper' 'ConvertTo-OrderedHashtable.ps1') . (Join-Path $PSScriptRoot 'Get-BRMRepositoryName.ps1') - . (Join-Path $PSScriptRoot 'helper' 'Get-CrossReferencedModuleList.ps1') + . (Join-Path $PSScriptRoot 'helper' 'Get-CrossReferencedModuleList.ps1') # Check template & make full path $TemplateFilePath = Resolve-Path -Path $TemplateFilePath -ErrorAction Stop From 59929d67c55c97cf65c9d0ed253cfadb3a664072 Mon Sep 17 00:00:00 2001 From: Kris Baranek Date: Thu, 21 Mar 2024 19:26:12 +0100 Subject: [PATCH 51/73] fix: Fixed WAF Reliability validation in `avm/res/network/public-ip-address` (#1367) ## Description Fixes failing WAF Reliability validation ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.network.public-ip-address](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.network.public-ip-address.yml/badge.svg?branch=users%2Fkrbar%2FpipWAF)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.network.public-ip-address.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [x] Azure Verified Module updates: - [ ] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [x] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [x] I have run `Set-AVMModule` locally to generate the supporting module files. - [x] My corresponding pipelines / checks run clean and green without any errors or warnings --- avm/res/network/public-ip-address/README.md | 8 ++++++++ avm/res/network/public-ip-address/main.bicep | 6 +++++- avm/res/network/public-ip-address/main.json | 10 +++++++--- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/avm/res/network/public-ip-address/README.md b/avm/res/network/public-ip-address/README.md index ffe18ec418..5acabdee51 100644 --- a/avm/res/network/public-ip-address/README.md +++ b/avm/res/network/public-ip-address/README.md @@ -929,6 +929,14 @@ A list of availability zones denoting the IP allocated for the resource needs to - Required: No - Type: array +- Default: + ```Bicep + [ + '1' + '2' + '3' + ] + ``` ## Outputs diff --git a/avm/res/network/public-ip-address/main.bicep b/avm/res/network/public-ip-address/main.bicep index d8463cb9a7..ef48ffb569 100644 --- a/avm/res/network/public-ip-address/main.bicep +++ b/avm/res/network/public-ip-address/main.bicep @@ -16,7 +16,11 @@ param publicIpPrefixResourceId string? param publicIPAllocationMethod string = 'Static' @description('Optional. A list of availability zones denoting the IP allocated for the resource needs to come from.') -param zones array? +param zones array = [ + '1' + '2' + '3' +] @description('Optional. IP address version.') @allowed([ diff --git a/avm/res/network/public-ip-address/main.json b/avm/res/network/public-ip-address/main.json index 77c39a8774..b1f2535b3f 100644 --- a/avm/res/network/public-ip-address/main.json +++ b/avm/res/network/public-ip-address/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "1322777943943789546" + "version": "0.26.54.24096", + "templateHash": "11299369930230398843" }, "name": "Public IP Addresses", "description": "This module deploys a Public IP Address.", @@ -318,7 +318,11 @@ }, "zones": { "type": "array", - "nullable": true, + "defaultValue": [ + "1", + "2", + "3" + ], "metadata": { "description": "Optional. A list of availability zones denoting the IP allocated for the resource needs to come from." } From a46cf8c9d1e6f839682f604609fa46637461bf54 Mon Sep 17 00:00:00 2001 From: Kris Baranek Date: Fri, 22 Mar 2024 10:05:19 +0100 Subject: [PATCH 52/73] feat: New Module `avm/res/web/connection` (#1318) ## Description New Module `avm/res/web/connection`, migrated from CARML. ## Adding a new module - [x] A proposal has been submitted and approved. - [ ] I have included "Closes #{module_proposal_issue_number}" in the PR description. - [ ] I have run `brm validate` locally to verify the module files. - [x] I have run deployment tests locally to ensure the module is deployable. ## Pipeline references | Pipeline | | - | | [![avm.res.web.connection](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.web.connection.yml/badge.svg?branch=users%2Fkrbar%2FwebConnModule)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.web.connection.yml) | --------- Co-authored-by: Alexander Sehr --- .github/CODEOWNERS | 2 +- .github/ISSUE_TEMPLATE/avm_module_issue.yml | 2 +- .github/workflows/avm.res.web.connection.yml | 86 +++ avm/res/web/connection/ORPHANED.md | 4 + avm/res/web/connection/README.md | 535 ++++++++++++++++++ avm/res/web/connection/main.bicep | 157 +++++ avm/res/web/connection/main.json | 310 ++++++++++ .../tests/e2e/defaults/main.test.bicep | 50 ++ .../tests/e2e/max/dependencies.bicep | 13 + .../connection/tests/e2e/max/main.test.bicep | 85 +++ .../tests/e2e/waf-aligned/main.test.bicep | 55 ++ avm/res/web/connection/version.json | 7 + 12 files changed, 1304 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/avm.res.web.connection.yml create mode 100644 avm/res/web/connection/ORPHANED.md create mode 100644 avm/res/web/connection/README.md create mode 100644 avm/res/web/connection/main.bicep create mode 100644 avm/res/web/connection/main.json create mode 100644 avm/res/web/connection/tests/e2e/defaults/main.test.bicep create mode 100644 avm/res/web/connection/tests/e2e/max/dependencies.bicep create mode 100644 avm/res/web/connection/tests/e2e/max/main.test.bicep create mode 100644 avm/res/web/connection/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/res/web/connection/version.json diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index a2e1e73bc0..8abb898450 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -135,7 +135,7 @@ /avm/res/synapse/private-link-hub/ @Azure/avm-res-synapse-privatelinkhub-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/synapse/workspace/ @Azure/avm-res-synapse-workspace-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/virtual-machine-images/image-template/ @Azure/avm-res-virtualmachineimages-imagetemplate-module-owners-bicep @Azure/avm-core-team-technical-bicep -#/avm/res/web/connection/ @Azure/avm-res-web-connection-module-owners-bicep @Azure/avm-core-team-technical-bicep +/avm/res/web/connection/ @Azure/avm-res-web-connection-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/web/hosting-environment/ @Azure/avm-res-web-hostingenvironment-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/web/serverfarm/ @Azure/avm-res-web-serverfarm-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/web/site/ @Azure/avm-res-web-site-module-owners-bicep @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 37fbffc58f..a2232bb2b2 100644 --- a/.github/ISSUE_TEMPLATE/avm_module_issue.yml +++ b/.github/ISSUE_TEMPLATE/avm_module_issue.yml @@ -169,7 +169,7 @@ body: - "avm/res/synapse/private-link-hub" - "avm/res/synapse/workspace" - "avm/res/virtual-machine-images/image-template" - # - "avm/res/web/connection" + - "avm/res/web/connection" # - "avm/res/web/hosting-environment" - "avm/res/web/serverfarm" - "avm/res/web/site" diff --git a/.github/workflows/avm.res.web.connection.yml b/.github/workflows/avm.res.web.connection.yml new file mode 100644 index 0000000000..c3b8b69c55 --- /dev/null +++ b/.github/workflows/avm.res.web.connection.yml @@ -0,0 +1,86 @@ +name: "avm.res.web.connection" + +on: + schedule: + - cron: "0 12 1/15 * *" # Bi-Weekly Test (on 1st & 15th of month) + 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 + push: + branches: + - main + paths: + - ".github/actions/templates/avm-**" + - ".github/workflows/avm.template.module.yml" + - ".github/workflows/avm.res.web.connection.yml" + - "avm/res/web/connection/**" + - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/web/connection" + workflowPath: ".github/workflows/avm.res.web.connection.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-latest + name: "Initialize pipeline" + steps: + - name: "Checkout" + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: "Set input parameters to output variables" + id: get-workflow-param + uses: ./.github/actions/templates/avm-getWorkflowInput + with: + workflowPath: "${{ env.workflowPath}}" + - name: "Get module test file paths" + id: get-module-test-file-paths + uses: ./.github/actions/templates/avm-getModuleTestFiles + with: + modulePath: "${{ env.modulePath }}" + outputs: + workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }} + moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} + psRuleModuleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.psRuleModuleTestFilePaths }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Run" + permissions: + id-token: write # For OIDC + contents: write # For release tags + needs: + - job_initialize_pipeline + uses: ./.github/workflows/avm.template.module.yml + with: + workflowInput: "${{ needs.job_initialize_pipeline.outputs.workflowInput }}" + moduleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.moduleTestFilePaths }}" + psRuleModuleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.psRuleModuleTestFilePaths }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit diff --git a/avm/res/web/connection/ORPHANED.md b/avm/res/web/connection/ORPHANED.md new file mode 100644 index 0000000000..ef8fa911d2 --- /dev/null +++ b/avm/res/web/connection/ORPHANED.md @@ -0,0 +1,4 @@ +⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ + +- Only security and bug fixes are being handled by the AVM core team at present. +- If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! \ No newline at end of file diff --git a/avm/res/web/connection/README.md b/avm/res/web/connection/README.md new file mode 100644 index 0000000000..e98d0eedbd --- /dev/null +++ b/avm/res/web/connection/README.md @@ -0,0 +1,535 @@ +# API Connections `[Microsoft.Web/connections]` + +> ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ +> +> - Only security and bug fixes are being handled by the AVM core team at present. +> - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! + +This module deploys an Azure API Connection. + +## Navigation + +- [Resource Types](#Resource-Types) +- [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` | [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.Web/connections` | [2016-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2016-06-01/connections) | + +## 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/res/web/connection:`. + +- [Using only defaults](#example-1-using-only-defaults) +- [Using large parameter set](#example-2-using-large-parameter-set) +- [WAF-aligned](#example-3-waf-aligned) + +### Example 1: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. + + +
+ +via Bicep module + +```bicep +module connection 'br/public:avm/res/web/connection:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-wcmin' + params: { + // Required parameters + displayName: 'azuremonitorlogs' + name: 'azuremonitor' + // Non-required parameters + api: { + id: '' + } + location: '' + } +} +``` + +
+

+ +

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

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

+ +via Bicep module + +```bicep +module connection 'br/public:avm/res/web/connection:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-wcmax' + params: { + // Required parameters + displayName: 'azuremonitorlogs' + name: 'azuremonitor' + // Non-required parameters + api: { + id: '' + } + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "displayName": { + "value": "azuremonitorlogs" + }, + "name": { + "value": "azuremonitor" + }, + // Non-required parameters + "api": { + "value": { + "id": "" + } + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module connection 'br/public:avm/res/web/connection:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-wcwaf' + params: { + // Required parameters + displayName: 'azuremonitorlogs' + name: 'azuremonitor' + // Non-required parameters + api: { + id: '' + } + location: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "displayName": { + "value": "azuremonitorlogs" + }, + "name": { + "value": "azuremonitor" + }, + // Non-required parameters + "api": { + "value": { + "id": "" + } + }, + "location": { + "value": "" + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

+ + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`displayName`](#parameter-displayname) | string | Display name connection. Example: 'blobconnection' when using blobs. It can change depending on the resource. | +| [`name`](#parameter-name) | string | Connection name for connection. Example: 'azureblob' when using blobs. It can change depending on the resource. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`api`](#parameter-api) | object | Specific values for some API connections. | +| [`customParameterValues`](#parameter-customparametervalues) | object | Customized parameter values for specific connections. | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`location`](#parameter-location) | string | Location of the deployment. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`nonSecretParameterValues`](#parameter-nonsecretparametervalues) | object | Dictionary of nonsecret parameter values. | +| [`parameterValues`](#parameter-parametervalues) | secureObject | Connection strings or access keys for connection. Example: 'accountName' and 'accessKey' when using blobs. It can change depending on the resource. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`statuses`](#parameter-statuses) | array | Status of the connection. | +| [`tags`](#parameter-tags) | object | Tags of the resource. | +| [`testLinks`](#parameter-testlinks) | array | Links to test the API connection. | + +### Parameter: `displayName` + +Display name connection. Example: 'blobconnection' when using blobs. It can change depending on the resource. + +- Required: Yes +- Type: string + +### Parameter: `name` + +Connection name for connection. Example: 'azureblob' when using blobs. It can change depending on the resource. + +- Required: Yes +- Type: string + +### Parameter: `api` + +Specific values for some API connections. + +- Required: No +- Type: object + +### Parameter: `customParameterValues` + +Customized parameter values for specific connections. + +- Required: No +- Type: object + +### Parameter: `enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `location` + +Location of the deployment. + +- 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: `nonSecretParameterValues` + +Dictionary of nonsecret parameter values. + +- Required: No +- Type: object + +### Parameter: `parameterValues` + +Connection strings or access keys for connection. Example: 'accountName' and 'accessKey' when using blobs. It can change depending on the resource. + +- Required: No +- Type: secureObject + +### Parameter: `roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**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. | +| [`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.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `statuses` + +Status of the connection. + +- Required: No +- Type: array + +### Parameter: `tags` + +Tags of the resource. + +- Required: No +- Type: object + +### Parameter: `testLinks` + +Links to test the API connection. + +- Required: No +- Type: array + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the connection. | +| `resourceGroupName` | string | The resource group the connection was deployed into. | +| `resourceId` | string | The resource ID of the connection. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/web/connection/main.bicep b/avm/res/web/connection/main.bicep new file mode 100644 index 0000000000..31e5a59982 --- /dev/null +++ b/avm/res/web/connection/main.bicep @@ -0,0 +1,157 @@ +metadata name = 'API Connections' +metadata description = 'This module deploys an Azure API Connection.' +metadata owner = 'Azure/module-maintainers' + +@description('Optional. Specific values for some API connections.') +param api object? + +@description('Required. Connection name for connection. Example: \'azureblob\' when using blobs. It can change depending on the resource.') +param name string + +@description('Optional. Enable/Disable usage telemetry for module.') +param enableTelemetry bool = true + +@description('Optional. Customized parameter values for specific connections.') +param customParameterValues object? + +@description('Required. Display name connection. Example: \'blobconnection\' when using blobs. It can change depending on the resource.') +param displayName string + +@description('Optional. Location of the deployment.') +param location string = resourceGroup().location + +@description('Optional. Dictionary of nonsecret parameter values.') +#disable-next-line secure-secrets-in-params // Not a secret +param nonSecretParameterValues object? + +@description('Optional. Connection strings or access keys for connection. Example: \'accountName\' and \'accessKey\' when using blobs. It can change depending on the resource.') +@secure() +param parameterValues object? + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +@description('Optional. Status of the connection.') +param statuses array? + +@description('Optional. The lock settings of the service.') +param lock lockType + +@description('Optional. Tags of the resource.') +param tags object? + +@description('Optional. Links to test the API connection.') +param testLinks array? + +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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.web-connection.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } + } + } + } +} + +resource connection 'Microsoft.Web/connections@2016-06-01' = { + name: name + location: location + tags: tags + properties: { + displayName: displayName + customParameterValues: customParameterValues + api: api + parameterValues: parameterValues + nonSecretParameterValues: nonSecretParameterValues + testLinks: testLinks + statuses: statuses + } +} + +resource connection_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: connection +} + +resource connection_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ +for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(connection.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: connection +} +] + +@description('The resource ID of the connection.') +output resourceId string = connection.id + +@description('The resource group the connection was deployed into.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the connection.') +output name string = connection.name + +@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('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 new file mode 100644 index 0000000000..42a8a1e6a1 --- /dev/null +++ b/avm/res/web/connection/main.json @@ -0,0 +1,310 @@ +{ + "$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.26.54.24096", + "templateHash": "7023218884574427074" + }, + "name": "API Connections", + "description": "This module deploys an Azure API Connection.", + "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": { + "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": { + "api": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Specific values for some API connections." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Connection name for connection. Example: 'azureblob' when using blobs. It can change depending on the resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "customParameterValues": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Customized parameter values for specific connections." + } + }, + "displayName": { + "type": "string", + "metadata": { + "description": "Required. Display name connection. Example: 'blobconnection' when using blobs. It can change depending on the resource." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location of the deployment." + } + }, + "nonSecretParameterValues": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Dictionary of nonsecret parameter values." + } + }, + "parameterValues": { + "type": "secureObject", + "nullable": true, + "metadata": { + "description": "Optional. Connection strings or access keys for connection. Example: 'accountName' and 'accessKey' when using blobs. It can change depending on the resource." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "statuses": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Status of the connection." + } + }, + "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." + } + }, + "testLinks": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Links to test the API connection." + } + } + }, + "variables": { + "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 (Preview)": "[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": "2023-07-01", + "name": "[format('46d3xbcp.res.web-connection.{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" + } + } + } + } + }, + "connection": { + "type": "Microsoft.Web/connections", + "apiVersion": "2016-06-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "displayName": "[parameters('displayName')]", + "customParameterValues": "[parameters('customParameterValues')]", + "api": "[parameters('api')]", + "parameterValues": "[parameters('parameterValues')]", + "nonSecretParameterValues": "[parameters('nonSecretParameterValues')]", + "testLinks": "[parameters('testLinks')]", + "statuses": "[parameters('statuses')]" + } + }, + "connection_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.Web/connections/{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": [ + "connection" + ] + }, + "connection_roleAssignments": { + "copy": { + "name": "connection_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Web/connections/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Web/connections', 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": [ + "connection" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the connection." + }, + "value": "[resourceId('Microsoft.Web/connections', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the connection was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the connection." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('connection', '2016-06-01', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/web/connection/tests/e2e/defaults/main.test.bicep b/avm/res/web/connection/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..95f389e687 --- /dev/null +++ b/avm/res/web/connection/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,50 @@ +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}-web.connections-${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 = 'wcmin' + +@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: { + displayName: 'azuremonitorlogs' + name: 'azuremonitor' + location: resourceLocation + api: { + id: '${subscription().id}/providers/Microsoft.Web/locations/${resourceLocation}/managedApis/azuremonitorlogs' + } + } +}] diff --git a/avm/res/web/connection/tests/e2e/max/dependencies.bicep b/avm/res/web/connection/tests/e2e/max/dependencies.bicep new file mode 100644 index 0000000000..a7f42aee7b --- /dev/null +++ b/avm/res/web/connection/tests/e2e/max/dependencies.bicep @@ -0,0 +1,13 @@ +@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 + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/web/connection/tests/e2e/max/main.test.bicep b/avm/res/web/connection/tests/e2e/max/main.test.bicep new file mode 100644 index 0000000000..e858b06c05 --- /dev/null +++ b/avm/res/web/connection/tests/e2e/max/main.test.bicep @@ -0,0 +1,85 @@ +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}-web.connections-${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 = 'wcmax' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + managedIdentityName: 'dep-${namePrefix}-msi-${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: { + displayName: 'azuremonitorlogs' + name: 'azuremonitor' + location: resourceLocation + api: { + id: '${subscription().id}/providers/Microsoft.Web/locations/${resourceLocation}/managedApis/azuremonitorlogs' + } + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/web/connection/tests/e2e/waf-aligned/main.test.bicep b/avm/res/web/connection/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..061f75713a --- /dev/null +++ b/avm/res/web/connection/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,55 @@ +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}-web.connections-${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 = 'wcwaf' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + displayName: 'azuremonitorlogs' + name: 'azuremonitor' + location: resourceLocation + api: { + id: '${subscription().id}/providers/Microsoft.Web/locations/${resourceLocation}/managedApis/azuremonitorlogs' + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/web/connection/version.json b/avm/res/web/connection/version.json new file mode 100644 index 0000000000..83083db694 --- /dev/null +++ b/avm/res/web/connection/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.1", + "pathFilters": [ + "./main.json" + ] +} \ No newline at end of file From 84e8045df170cd0094f9ea895639144fe9498251 Mon Sep 17 00:00:00 2001 From: Kris Baranek Date: Fri, 22 Mar 2024 12:02:54 +0100 Subject: [PATCH 53/73] fix: Patch of `avm/res/web/connection` to enforce the publishing (#1387) ## Description Patch of `avm/res/web/connection` to enforce the publishing ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.web.connection](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.web.connection.yml/badge.svg?branch=users%2Fkrbar%2FwebConnFix)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.web.connection.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [x] Azure Verified Module updates: - [x] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [x] I have run `Set-AVMModule` locally to generate the supporting module files. - [x] My corresponding pipelines / checks run clean and green without any errors or warnings --- avm/res/web/connection/README.md | 14 +++++++------- avm/res/web/connection/main.bicep | 4 ++-- avm/res/web/connection/main.json | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/avm/res/web/connection/README.md b/avm/res/web/connection/README.md index e98d0eedbd..3215e264f7 100644 --- a/avm/res/web/connection/README.md +++ b/avm/res/web/connection/README.md @@ -47,7 +47,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module connection 'br/public:avm/res/web/connection:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-wcmin' + name: 'connectionDeployment' params: { // Required parameters displayName: 'azuremonitorlogs' @@ -107,7 +107,7 @@ This instance deploys the module with most of its features enabled. ```bicep module connection 'br/public:avm/res/web/connection:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-wcmax' + name: 'connectionDeployment' params: { // Required parameters displayName: 'azuremonitorlogs' @@ -225,7 +225,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module connection 'br/public:avm/res/web/connection:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-wcwaf' + name: 'connectionDeployment' params: { // Required parameters displayName: 'azuremonitorlogs' @@ -294,14 +294,14 @@ module connection 'br/public:avm/res/web/connection:' = { | Parameter | Type | Description | | :-- | :-- | :-- | | [`displayName`](#parameter-displayname) | string | Display name connection. Example: 'blobconnection' when using blobs. It can change depending on the resource. | -| [`name`](#parameter-name) | string | Connection name for connection. Example: 'azureblob' when using blobs. It can change depending on the resource. | +| [`name`](#parameter-name) | string | Connection name for connection. Example: 'azureblob' when using blobs. It can change depending on the resource. | **Optional parameters** | Parameter | Type | Description | | :-- | :-- | :-- | | [`api`](#parameter-api) | object | Specific values for some API connections. | -| [`customParameterValues`](#parameter-customparametervalues) | object | Customized parameter values for specific connections. | +| [`customParameterValues`](#parameter-customparametervalues) | object | Dictionary of custom parameter values for specific connections. | | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`location`](#parameter-location) | string | Location of the deployment. | | [`lock`](#parameter-lock) | object | The lock settings of the service. | @@ -321,7 +321,7 @@ Display name connection. Example: 'blobconnection' when using blobs. It can chan ### Parameter: `name` -Connection name for connection. Example: 'azureblob' when using blobs. It can change depending on the resource. +Connection name for connection. Example: 'azureblob' when using blobs. It can change depending on the resource. - Required: Yes - Type: string @@ -335,7 +335,7 @@ Specific values for some API connections. ### Parameter: `customParameterValues` -Customized parameter values for specific connections. +Dictionary of custom parameter values for specific connections. - Required: No - Type: object diff --git a/avm/res/web/connection/main.bicep b/avm/res/web/connection/main.bicep index 31e5a59982..4a9150f8cd 100644 --- a/avm/res/web/connection/main.bicep +++ b/avm/res/web/connection/main.bicep @@ -5,13 +5,13 @@ metadata owner = 'Azure/module-maintainers' @description('Optional. Specific values for some API connections.') param api object? -@description('Required. Connection name for connection. Example: \'azureblob\' when using blobs. It can change depending on the resource.') +@description('Required. Connection name for connection. Example: \'azureblob\' when using blobs. It can change depending on the resource.') param name string @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -@description('Optional. Customized parameter values for specific connections.') +@description('Optional. Dictionary of custom parameter values for specific connections.') param customParameterValues object? @description('Required. Display name connection. Example: \'blobconnection\' when using blobs. It can change depending on the resource.') diff --git a/avm/res/web/connection/main.json b/avm/res/web/connection/main.json index 42a8a1e6a1..b8ead16876 100644 --- a/avm/res/web/connection/main.json +++ b/avm/res/web/connection/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.26.54.24096", - "templateHash": "7023218884574427074" + "templateHash": "153462740137838298" }, "name": "API Connections", "description": "This module deploys an Azure API Connection.", @@ -116,7 +116,7 @@ "name": { "type": "string", "metadata": { - "description": "Required. Connection name for connection. Example: 'azureblob' when using blobs. It can change depending on the resource." + "description": "Required. Connection name for connection. Example: 'azureblob' when using blobs. It can change depending on the resource." } }, "enableTelemetry": { @@ -130,7 +130,7 @@ "type": "object", "nullable": true, "metadata": { - "description": "Optional. Customized parameter values for specific connections." + "description": "Optional. Dictionary of custom parameter values for specific connections." } }, "displayName": { From 7abb6cf9d0db2dc670955a41da1647ffff6446c2 Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Fri, 22 Mar 2024 12:16:48 +0000 Subject: [PATCH 54/73] feat: New Module `digital-twins/digital-twins-instance` (#1277) ## Description Adding new module for Digital Twins instance ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.digital-twins.digital-twins-instance](https://github.com/ChrisSidebotham/bicep-registry-modules/actions/workflows/avm.res.digital-twins.digital-twins-instance.yml/badge.svg?event=workflow_dispatch)](https://github.com/ChrisSidebotham/bicep-registry-modules/actions/workflows/avm.res.digital-twins.digital-twins-instance.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [x] Azure Verified Module updates: - [ ] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [x] I have run `Set-AVMModule` locally to generate the supporting module files. - [ ] My corresponding pipelines / checks run clean and green without any errors or warnings --------- Co-authored-by: Alexander Sehr --- .github/CODEOWNERS | 2 +- .github/ISSUE_TEMPLATE/avm_module_issue.yml | 2 +- ...s.digital-twins.digital-twins-instance.yml | 85 + .../digital-twins-instance/README.md | 1201 +++++++++++ .../endpoint--event-grid/README.md | 102 + .../endpoint--event-grid/main.bicep | 49 + .../endpoint--event-grid/main.json | 94 + .../endpoint--event-hub/README.md | 163 ++ .../endpoint--event-hub/main.bicep | 91 + .../endpoint--event-hub/main.json | 175 ++ .../endpoint--service-bus/README.md | 163 ++ .../endpoint--service-bus/main.bicep | 92 + .../endpoint--service-bus/main.json | 175 ++ .../digital-twins-instance/main.bicep | 408 ++++ .../digital-twins-instance/main.json | 1891 +++++++++++++++++ .../tests/e2e/defaults/main.test.bicep | 45 + .../tests/e2e/max/dependencies.bicep | 162 ++ .../tests/e2e/max/main.test.bicep | 152 ++ .../tests/e2e/pe/dependencies.bicep | 68 + .../tests/e2e/pe/main.test.bicep | 72 + .../tests/e2e/waf-aligned/main.test.bicep | 76 + .../digital-twins-instance/version.json | 7 + 22 files changed, 5273 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/avm.res.digital-twins.digital-twins-instance.yml create mode 100644 avm/res/digital-twins/digital-twins-instance/README.md create mode 100644 avm/res/digital-twins/digital-twins-instance/endpoint--event-grid/README.md create mode 100644 avm/res/digital-twins/digital-twins-instance/endpoint--event-grid/main.bicep create mode 100644 avm/res/digital-twins/digital-twins-instance/endpoint--event-grid/main.json create mode 100644 avm/res/digital-twins/digital-twins-instance/endpoint--event-hub/README.md create mode 100644 avm/res/digital-twins/digital-twins-instance/endpoint--event-hub/main.bicep create mode 100644 avm/res/digital-twins/digital-twins-instance/endpoint--event-hub/main.json create mode 100644 avm/res/digital-twins/digital-twins-instance/endpoint--service-bus/README.md create mode 100644 avm/res/digital-twins/digital-twins-instance/endpoint--service-bus/main.bicep create mode 100644 avm/res/digital-twins/digital-twins-instance/endpoint--service-bus/main.json create mode 100644 avm/res/digital-twins/digital-twins-instance/main.bicep create mode 100644 avm/res/digital-twins/digital-twins-instance/main.json create mode 100644 avm/res/digital-twins/digital-twins-instance/tests/e2e/defaults/main.test.bicep create mode 100644 avm/res/digital-twins/digital-twins-instance/tests/e2e/max/dependencies.bicep create mode 100644 avm/res/digital-twins/digital-twins-instance/tests/e2e/max/main.test.bicep create mode 100644 avm/res/digital-twins/digital-twins-instance/tests/e2e/pe/dependencies.bicep create mode 100644 avm/res/digital-twins/digital-twins-instance/tests/e2e/pe/main.test.bicep create mode 100644 avm/res/digital-twins/digital-twins-instance/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/res/digital-twins/digital-twins-instance/version.json diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 8abb898450..c940e9a12e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -46,7 +46,7 @@ /avm/res/desktop-virtualization/workspace/ @Azure/avm-res-desktopvirtualization-workspace-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/dev-center/devcenter/ @Azure/avm-res-devcenter-devcenter-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/dev-test-lab/lab/ @Azure/avm-res-devtestlab-lab-module-owners-bicep @Azure/avm-core-team-technical-bicep -#/avm/res/digital-twins/digital-twins-instance/ @Azure/avm-res-digitaltwins-digitaltwinsinstance-module-owners-bicep @Azure/avm-core-team-technical-bicep +/avm/res/digital-twins/digital-twins-instance/ @Azure/avm-res-digitaltwins-digitaltwinsinstance-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/document-db/database-account/ @Azure/avm-res-documentdb-databaseaccount-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/event-grid/domain/ @Azure/avm-res-eventgrid-domain-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/event-grid/namespace/ @Azure/avm-res-eventgrid-namespace-module-owners-bicep @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 a2232bb2b2..71401f6c31 100644 --- a/.github/ISSUE_TEMPLATE/avm_module_issue.yml +++ b/.github/ISSUE_TEMPLATE/avm_module_issue.yml @@ -80,7 +80,7 @@ body: - "avm/res/desktop-virtualization/workspace" # - "avm/res/dev-center/devcenter" - "avm/res/dev-test-lab/lab" - # - "avm/res/digital-twins/digital-twins-instance" + - "avm/res/digital-twins/digital-twins-instance" - "avm/res/document-db/database-account" - "avm/res/event-grid/domain" - "avm/res/event-grid/namespace" diff --git a/.github/workflows/avm.res.digital-twins.digital-twins-instance.yml b/.github/workflows/avm.res.digital-twins.digital-twins-instance.yml new file mode 100644 index 0000000000..71b6b56d1a --- /dev/null +++ b/.github/workflows/avm.res.digital-twins.digital-twins-instance.yml @@ -0,0 +1,85 @@ +name: "avm.res.digital-twins.digital-twins-instance" + +on: + schedule: + - cron: "0 12 1/15 * *" # Bi-Weekly Test (on 1st & 15th of month) + 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 + push: + branches: + - main + paths: + - ".github/actions/templates/avm-**" + - ".github/workflows/avm.template.module.yml" + - ".github/workflows/avm.res.digital-twins.digital-twins-instance.yml" + - "avm/res/digital-twins/digital-twins-instance/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/digital-twins/digital-twins-instance" + workflowPath: ".github/workflows/avm.res.digital-twins.digital-twins-instance.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-latest + name: "Initialize pipeline" + steps: + - name: "Checkout" + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: "Set input parameters to output variables" + id: get-workflow-param + uses: ./.github/actions/templates/avm-getWorkflowInput + with: + workflowPath: "${{ env.workflowPath}}" + - name: "Get module test file paths" + id: get-module-test-file-paths + uses: ./.github/actions/templates/avm-getModuleTestFiles + with: + modulePath: "${{ env.modulePath }}" + outputs: + workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }} + moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} + psRuleModuleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.psRuleModuleTestFilePaths }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Run" + permissions: + id-token: write # For OIDC + contents: write # For release tags + needs: + - job_initialize_pipeline + uses: ./.github/workflows/avm.template.module.yml + with: + workflowInput: "${{ needs.job_initialize_pipeline.outputs.workflowInput }}" + moduleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.moduleTestFilePaths }}" + psRuleModuleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.psRuleModuleTestFilePaths }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit diff --git a/avm/res/digital-twins/digital-twins-instance/README.md b/avm/res/digital-twins/digital-twins-instance/README.md new file mode 100644 index 0000000000..ecd905bd7f --- /dev/null +++ b/avm/res/digital-twins/digital-twins-instance/README.md @@ -0,0 +1,1201 @@ +# Digital Twins Instances `[Microsoft.DigitalTwins/digitalTwinsInstances]` + +This module deploys an Azure Digital Twins Instance. + +## Navigation + +- [Resource Types](#Resource-Types) +- [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` | [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.DigitalTwins/digitalTwinsInstances` | [2023-01-31](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DigitalTwins/2023-01-31/digitalTwinsInstances) | +| `Microsoft.DigitalTwins/digitalTwinsInstances/endpoints` | [2023-01-31](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DigitalTwins/2023-01-31/digitalTwinsInstances/endpoints) | +| `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) | + +## 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/res/digital-twins/digital-twins-instance:`. + +- [Using only defaults](#example-1-using-only-defaults) +- [Using large parameter set](#example-2-using-large-parameter-set) +- [Using private endpoint parameter set](#example-3-using-private-endpoint-parameter-set) +- [WAF-aligned](#example-4-waf-aligned) + +### Example 1: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. + + +

+ +via Bicep module + +```bicep +module digitalTwinsInstance 'br/public:avm/res/digital-twins/digital-twins-instance:' = { + name: 'digitalTwinsInstanceDeployment' + params: { + name: 'dtdtimin001' + } +} +``` + +
+

+ +

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

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

+ +via Bicep module + +```bicep +module digitalTwinsInstance 'br/public:avm/res/digital-twins/digital-twins-instance:' = { + name: 'digitalTwinsInstanceDeployment' + params: { + // Required parameters + name: 'dtdtimax001' + // Non-required parameters + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + eventGridEndpoint: { + eventGridDomainId: '' + topicEndpoint: '' + } + eventHubEndpoint: { + authenticationType: 'IdentityBased' + endpointUri: '' + entityPath: '' + managedIdentities: { + userAssignedResourceId: '' + } + } + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + '' + ] + } + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + '' + ] + subnetResourceId: '' + } + ] + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + serviceBusEndpoint: { + authenticationType: 'IdentityBased' + endpointUri: '' + entityPath: '' + managedIdentities: { + userAssignedResourceId: '' + } + } + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "dtdtimax001" + }, + // Non-required parameters + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "eventGridEndpoint": { + "value": { + "eventGridDomainId": "", + "topicEndpoint": "" + } + }, + "eventHubEndpoint": { + "value": { + "authenticationType": "IdentityBased", + "endpointUri": "", + "entityPath": "", + "managedIdentities": { + "userAssignedResourceId": "" + } + } + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "managedIdentities": { + "value": { + "systemAssigned": true, + "userAssignedResourceIds": [ + "" + ] + } + }, + "privateEndpoints": { + "value": [ + { + "privateDnsZoneResourceIds": [ + "" + ], + "subnetResourceId": "" + } + ] + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "serviceBusEndpoint": { + "value": { + "authenticationType": "IdentityBased", + "endpointUri": "", + "entityPath": "", + "managedIdentities": { + "userAssignedResourceId": "" + } + } + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

+ +### Example 3: _Using private endpoint parameter set_ + +This instance deploys the module with idempotancy tests for private endpoints. + + +

+ +via Bicep module + +```bicep +module digitalTwinsInstance 'br/public:avm/res/digital-twins/digital-twins-instance:' = { + name: 'digitalTwinsInstanceDeployment' + params: { + // Required parameters + name: 'dtdtipep001' + // Non-required parameters + location: '' + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + '' + ] + subnetResourceId: '' + } + { + privateDnsZoneResourceIds: [ + '' + ] + subnetResourceId: '' + } + ] + } +} +``` + +
+

+ +

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

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

+ +via Bicep module + +```bicep +module digitalTwinsInstance 'br/public:avm/res/digital-twins/digital-twins-instance:' = { + name: 'digitalTwinsInstanceDeployment' + params: { + // Required parameters + name: 'dtdtiwaf001' + // Non-required parameters + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + location: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "dtdtiwaf001" + }, + // Non-required parameters + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "location": { + "value": "" + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

+ + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | The name of the Digital Twin Instance. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`eventGridEndpoint`](#parameter-eventgridendpoint) | object | Event Grid Endpoint. | +| [`eventHubEndpoint`](#parameter-eventhubendpoint) | object | Event Hub Endpoint. | +| [`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. | +| [`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. | +| [`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'. | +| [`serviceBusEndpoint`](#parameter-servicebusendpoint) | object | Service Bus Endpoint. | +| [`tags`](#parameter-tags) | object | Resource tags. | + +### Parameter: `name` + +The name of the Digital Twin Instance. + +- Required: Yes +- Type: string + +### Parameter: `diagnosticSettings` + +The diagnostic settings of the service. + +- Required: No +- Type: array + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`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 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. | +| [`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. | + +### Parameter: `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: `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: `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: `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. + +- Required: No +- Type: string + +### Parameter: `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-diagnosticsettingsmetriccategoriescategory) | 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-diagnosticsettingsmetriccategoriesenabled) | bool | Enable or disable the category explicitly. Default is `true`. | + +### Parameter: `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: `diagnosticSettings.metricCategories.enabled` + +Enable or disable the category explicitly. Default is `true`. + +- Required: No +- Type: bool + +### Parameter: `diagnosticSettings.name` + +The name of diagnostic setting. + +- Required: No +- Type: string + +### Parameter: `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: `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: `enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `eventGridEndpoint` + +Event Grid Endpoint. + +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `eventHubEndpoint` + +Event Hub Endpoint. + +- Required: No +- Type: object +- Default: `{}` + +### 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. + +- 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. | + +### 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: No +- Type: array + +### Parameter: `privateEndpoints` + +Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`subnetResourceId`](#parameter-privateendpointssubnetresourceid) | string | Resource ID of the subnet where the endpoint needs to be created. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`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. | +| [`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. | +| [`isManualConnection`](#parameter-privateendpointsismanualconnection) | bool | If Manual Private Link Connection is required. | +| [`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. | +| [`resourceGroupName`](#parameter-privateendpointsresourcegroupname) | string | Specify if you want to deploy the Privte 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. | + +### Parameter: `privateEndpoints.subnetResourceId` + +Resource ID of the subnet where the endpoint needs to be created. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.applicationSecurityGroupResourceIds` + +Application security groups in which the private endpoint IP configuration is included. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.customDnsConfigs` + +Custom DNS configurations. + +- Required: No +- Type: array + +**Required parameters** + +| 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. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` + +A list of private IP addresses of the private endpoint. + +- Required: Yes +- Type: array + +### Parameter: `privateEndpoints.customNetworkInterfaceName` + +The custom name of the network interface attached to the private endpoint. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool + +### Parameter: `privateEndpoints.ipConfigurations` + +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 + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-privateendpointsipconfigurationsname) | string | The name of the resource that is unique within a resource group. | +| [`properties`](#parameter-privateendpointsipconfigurationsproperties) | object | Properties of private endpoint IP configurations. | + +### Parameter: `privateEndpoints.ipConfigurations.name` + +The name of the resource that is unique within a resource group. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.ipConfigurations.properties` + +Properties of private endpoint IP configurations. + +- Required: Yes +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`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. | + +### Parameter: `privateEndpoints.ipConfigurations.properties.groupId` + +The ID of a group obtained from the remote resource that this private endpoint should connect to. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.ipConfigurations.properties.memberName` + +The member name of a group obtained from the remote resource that this private endpoint should connect to. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.ipConfigurations.properties.privateIPAddress` + +A private IP address obtained from the private endpoint's subnet. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.isManualConnection` + +If Manual Private Link Connection is required. + +- Required: No +- Type: bool + +### Parameter: `privateEndpoints.location` + +The location to deploy the private endpoint to. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.lock` + +Specify the type of lock. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`kind`](#parameter-privateendpointslockkind) | string | Specify the type of lock. | +| [`name`](#parameter-privateendpointslockname) | string | Specify the name of lock. | + +### Parameter: `privateEndpoints.lock.kind` + +Specify the type of lock. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'CanNotDelete' + 'None' + 'ReadOnly' + ] + ``` + +### Parameter: `privateEndpoints.lock.name` + +Specify the name of lock. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.manualConnectionRequestMessage` + +A message passed to the owner of the remote resource with the manual connection request. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.name` + +The name of the private endpoint. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.privateDnsZoneGroupName` + +The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.privateDnsZoneResourceIds` + +The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.resourceGroupName` + +Specify if you want to deploy the Privte Endpoint into a different resource group than the main resource. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`principalId`](#parameter-privateendpointsroleassignmentsprincipalid) | string | The principal ID of the principal (user/group/identity) to assign the role to. | +| [`roleDefinitionIdOrName`](#parameter-privateendpointsroleassignmentsroledefinitionidorname) | 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-privateendpointsroleassignmentscondition) | 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-privateendpointsroleassignmentsconditionversion) | string | Version of the condition. | +| [`delegatedManagedIdentityResourceId`](#parameter-privateendpointsroleassignmentsdelegatedmanagedidentityresourceid) | string | The Resource Id of the delegated managed identity resource. | +| [`description`](#parameter-privateendpointsroleassignmentsdescription) | string | The description of the role assignment. | +| [`principalType`](#parameter-privateendpointsroleassignmentsprincipaltype) | string | The principal type of the assigned principal ID. | + +### Parameter: `privateEndpoints.roleAssignments.principalId` + +The principal ID of the principal (user/group/identity) to assign the role to. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.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: `privateEndpoints.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: `privateEndpoints.roleAssignments.conditionVersion` + +Version of the condition. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + '2.0' + ] + ``` + +### Parameter: `privateEndpoints.roleAssignments.delegatedManagedIdentityResourceId` + +The Resource Id of the delegated managed identity resource. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.roleAssignments.description` + +The description of the role assignment. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.roleAssignments.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `privateEndpoints.service` + +The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.tags` + +Tags to be applied on all resources/resource groups in this deployment. + +- Required: No +- Type: object + +### Parameter: `publicNetworkAccess` + +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. + +- Required: No +- Type: string +- Default: `''` +- Allowed: + ```Bicep + [ + '' + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `roleAssignments` + +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'. + +- Required: No +- Type: array + +**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. | +| [`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.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `serviceBusEndpoint` + +Service Bus Endpoint. + +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `tags` + +Resource tags. + +- Required: No +- Type: object + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `hostname` | string | The hostname of the Digital Twins Instance. | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the Digital Twins Instance. | +| `resourceGroupName` | string | The name of the resource group the resource was created in. | +| `resourceId` | string | The resource ID of the Digital Twins Instance. | +| `systemAssignedMIPrincipalId` | string | The principal ID of the system assigned identity. | + +## 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/network/private-endpoint:0.4.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/digital-twins/digital-twins-instance/endpoint--event-grid/README.md b/avm/res/digital-twins/digital-twins-instance/endpoint--event-grid/README.md new file mode 100644 index 0000000000..fc5fd51392 --- /dev/null +++ b/avm/res/digital-twins/digital-twins-instance/endpoint--event-grid/README.md @@ -0,0 +1,102 @@ +# Digital Twins Instance Event Grid Endpoints `[Microsoft.DigitalTwins/digitalTwinsInstances/endpoints]` + +This module deploys a Digital Twins Instance Event Grid Endpoint. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.DigitalTwins/digitalTwinsInstances/endpoints` | [2023-01-31](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DigitalTwins/2023-01-31/digitalTwinsInstances/endpoints) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`eventGridDomainResourceId`](#parameter-eventgriddomainresourceid) | string | The resource ID of the Event Grid to get access keys from. | +| [`topicEndpoint`](#parameter-topicendpoint) | string | EventGrid Topic Endpoint. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`digitalTwinInstanceName`](#parameter-digitaltwininstancename) | string | The name of the parent Digital Twin Instance resource. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`deadLetterSecret`](#parameter-deadlettersecret) | securestring | Dead letter storage secret for key-based authentication. Will be obfuscated during read. | +| [`deadLetterUri`](#parameter-deadletteruri) | string | Dead letter storage URL for identity-based authentication. | +| [`name`](#parameter-name) | string | The name of the Digital Twin Endpoint. | + +### Parameter: `eventGridDomainResourceId` + +The resource ID of the Event Grid to get access keys from. + +- Required: Yes +- Type: string + +### Parameter: `topicEndpoint` + +EventGrid Topic Endpoint. + +- Required: Yes +- Type: string + +### Parameter: `digitalTwinInstanceName` + +The name of the parent Digital Twin Instance resource. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `deadLetterSecret` + +Dead letter storage secret for key-based authentication. Will be obfuscated during read. + +- Required: No +- Type: securestring +- Default: `''` + +### Parameter: `deadLetterUri` + +Dead letter storage URL for identity-based authentication. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `name` + +The name of the Digital Twin Endpoint. + +- Required: No +- Type: string +- Default: `'EventGridEndpoint'` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Endpoint. | +| `resourceGroupName` | string | The name of the resource group the resource was created in. | +| `resourceId` | string | The resource ID of the Endpoint. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/digital-twins/digital-twins-instance/endpoint--event-grid/main.bicep b/avm/res/digital-twins/digital-twins-instance/endpoint--event-grid/main.bicep new file mode 100644 index 0000000000..5b975da92c --- /dev/null +++ b/avm/res/digital-twins/digital-twins-instance/endpoint--event-grid/main.bicep @@ -0,0 +1,49 @@ +metadata name = 'Digital Twins Instance Event Grid Endpoints' +metadata description = 'This module deploys a Digital Twins Instance Event Grid Endpoint.' +metadata owner = 'Azure/module-maintainers' + +@description('Optional. The name of the Digital Twin Endpoint.') +param name string = 'EventGridEndpoint' + +@description('Conditional. The name of the parent Digital Twin Instance resource. Required if the template is used in a standalone deployment.') +param digitalTwinInstanceName string + +@description('Required. EventGrid Topic Endpoint.') +param topicEndpoint string + +@description('Required. The resource ID of the Event Grid to get access keys from.') +param eventGridDomainResourceId string + +@description('Optional. Dead letter storage secret for key-based authentication. Will be obfuscated during read.') +@secure() +param deadLetterSecret string = '' + +@description('Optional. Dead letter storage URL for identity-based authentication.') +param deadLetterUri string = '' + +resource digitalTwinsInstance 'Microsoft.DigitalTwins/digitalTwinsInstances@2023-01-31' existing = { + name: digitalTwinInstanceName +} + +resource endpoint 'Microsoft.DigitalTwins/digitalTwinsInstances/endpoints@2023-01-31' = { + name: name + parent: digitalTwinsInstance + properties: { + endpointType: 'EventGrid' + authenticationType: 'KeyBased' + TopicEndpoint: topicEndpoint + accessKey1: listkeys(eventGridDomainResourceId, '2022-06-15').key1 + accessKey2: listkeys(eventGridDomainResourceId, '2022-06-15').key2 + deadLetterSecret: deadLetterSecret + deadLetterUri: deadLetterUri + } +} + +@description('The resource ID of the Endpoint.') +output resourceId string = endpoint.id + +@description('The name of the resource group the resource was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the Endpoint.') +output name string = endpoint.name diff --git a/avm/res/digital-twins/digital-twins-instance/endpoint--event-grid/main.json b/avm/res/digital-twins/digital-twins-instance/endpoint--event-grid/main.json new file mode 100644 index 0000000000..ea78396495 --- /dev/null +++ b/avm/res/digital-twins/digital-twins-instance/endpoint--event-grid/main.json @@ -0,0 +1,94 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.26.54.24096", + "templateHash": "11981298053277690078" + }, + "name": "Digital Twins Instance Event Grid Endpoints", + "description": "This module deploys a Digital Twins Instance Event Grid Endpoint.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "EventGridEndpoint", + "metadata": { + "description": "Optional. The name of the Digital Twin Endpoint." + } + }, + "digitalTwinInstanceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Digital Twin Instance resource. Required if the template is used in a standalone deployment." + } + }, + "topicEndpoint": { + "type": "string", + "metadata": { + "description": "Required. EventGrid Topic Endpoint." + } + }, + "eventGridDomainResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the Event Grid to get access keys from." + } + }, + "deadLetterSecret": { + "type": "securestring", + "defaultValue": "", + "metadata": { + "description": "Optional. Dead letter storage secret for key-based authentication. Will be obfuscated during read." + } + }, + "deadLetterUri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Dead letter storage URL for identity-based authentication." + } + } + }, + "resources": [ + { + "type": "Microsoft.DigitalTwins/digitalTwinsInstances/endpoints", + "apiVersion": "2023-01-31", + "name": "[format('{0}/{1}', parameters('digitalTwinInstanceName'), parameters('name'))]", + "properties": { + "endpointType": "EventGrid", + "authenticationType": "KeyBased", + "TopicEndpoint": "[parameters('topicEndpoint')]", + "accessKey1": "[listkeys(parameters('eventGridDomainResourceId'), '2022-06-15').key1]", + "accessKey2": "[listkeys(parameters('eventGridDomainResourceId'), '2022-06-15').key2]", + "deadLetterSecret": "[parameters('deadLetterSecret')]", + "deadLetterUri": "[parameters('deadLetterUri')]" + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Endpoint." + }, + "value": "[resourceId('Microsoft.DigitalTwins/digitalTwinsInstances/endpoints', parameters('digitalTwinInstanceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the resource was created in." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the Endpoint." + }, + "value": "[parameters('name')]" + } + } +} \ No newline at end of file diff --git a/avm/res/digital-twins/digital-twins-instance/endpoint--event-hub/README.md b/avm/res/digital-twins/digital-twins-instance/endpoint--event-hub/README.md new file mode 100644 index 0000000000..4a9c5acf08 --- /dev/null +++ b/avm/res/digital-twins/digital-twins-instance/endpoint--event-hub/README.md @@ -0,0 +1,163 @@ +# Digital Twins Instance EventHub Endpoint `[Microsoft.DigitalTwins/digitalTwinsInstances/endpoints]` + +This module deploys a Digital Twins Instance EventHub Endpoint. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.DigitalTwins/digitalTwinsInstances/endpoints` | [2023-01-31](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DigitalTwins/2023-01-31/digitalTwinsInstances/endpoints) | + +## Parameters + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`connectionStringPrimaryKey`](#parameter-connectionstringprimarykey) | securestring | PrimaryConnectionString of the endpoint for key-based authentication. Will be obfuscated during read. Required if the `authenticationType` is "KeyBased". | +| [`digitalTwinInstanceName`](#parameter-digitaltwininstancename) | string | The name of the parent Digital Twin Instance resource. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`authenticationType`](#parameter-authenticationtype) | string | Specifies the authentication type being used for connecting to the endpoint. If 'KeyBased' is selected, a connection string must be specified (at least the primary connection string). If 'IdentityBased' is selected, the endpointUri and entityPath properties must be specified. | +| [`connectionStringSecondaryKey`](#parameter-connectionstringsecondarykey) | securestring | SecondaryConnectionString of the endpoint for key-based authentication. Will be obfuscated during read. Only used if the `authenticationType` is "KeyBased". | +| [`deadLetterSecret`](#parameter-deadlettersecret) | securestring | Dead letter storage secret for key-based authentication. Will be obfuscated during read. | +| [`deadLetterUri`](#parameter-deadletteruri) | string | Dead letter storage URL for identity-based authentication. | +| [`endpointUri`](#parameter-endpointuri) | string | The URL of the EventHub namespace for identity-based authentication. It must include the protocol 'sb://' (i.e. sb://xyz.servicebus.windows.net). | +| [`entityPath`](#parameter-entitypath) | string | The EventHub name in the EventHub namespace for identity-based authentication. | +| [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. | +| [`name`](#parameter-name) | string | The name of the Digital Twin Endpoint. | + +### Parameter: `connectionStringPrimaryKey` + +PrimaryConnectionString of the endpoint for key-based authentication. Will be obfuscated during read. Required if the `authenticationType` is "KeyBased". + +- Required: No +- Type: securestring +- Default: `''` + +### Parameter: `digitalTwinInstanceName` + +The name of the parent Digital Twin Instance resource. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `authenticationType` + +Specifies the authentication type being used for connecting to the endpoint. If 'KeyBased' is selected, a connection string must be specified (at least the primary connection string). If 'IdentityBased' is selected, the endpointUri and entityPath properties must be specified. + +- Required: No +- Type: string +- Default: `'IdentityBased'` +- Allowed: + ```Bicep + [ + 'IdentityBased' + 'KeyBased' + ] + ``` + +### Parameter: `connectionStringSecondaryKey` + +SecondaryConnectionString of the endpoint for key-based authentication. Will be obfuscated during read. Only used if the `authenticationType` is "KeyBased". + +- Required: No +- Type: securestring +- Default: `''` + +### Parameter: `deadLetterSecret` + +Dead letter storage secret for key-based authentication. Will be obfuscated during read. + +- Required: No +- Type: securestring +- Default: `''` + +### Parameter: `deadLetterUri` + +Dead letter storage URL for identity-based authentication. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `endpointUri` + +The URL of the EventHub namespace for identity-based authentication. It must include the protocol 'sb://' (i.e. sb://xyz.servicebus.windows.net). + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `entityPath` + +The EventHub name in the EventHub namespace for identity-based authentication. + +- Required: No +- Type: string +- Default: `''` + +### 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. | + +### 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: No +- Type: array + +### Parameter: `name` + +The name of the Digital Twin Endpoint. + +- Required: No +- Type: string +- Default: `'EventHubEndpoint'` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Endpoint. | +| `resourceGroupName` | string | The name of the resource group the resource was created in. | +| `resourceId` | string | The resource ID of the Endpoint. | +| `systemAssignedMIPrincipalId` | string | The principal ID of the system assigned identity. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/digital-twins/digital-twins-instance/endpoint--event-hub/main.bicep b/avm/res/digital-twins/digital-twins-instance/endpoint--event-hub/main.bicep new file mode 100644 index 0000000000..c2588b6dbf --- /dev/null +++ b/avm/res/digital-twins/digital-twins-instance/endpoint--event-hub/main.bicep @@ -0,0 +1,91 @@ +metadata name = 'Digital Twins Instance EventHub Endpoint' +metadata description = 'This module deploys a Digital Twins Instance EventHub Endpoint.' +metadata owner = 'Azure/module-maintainers' + +@description('Optional. The name of the Digital Twin Endpoint.') +param name string = 'EventHubEndpoint' + +@description('Conditional. The name of the parent Digital Twin Instance resource. Required if the template is used in a standalone deployment.') +param digitalTwinInstanceName string + +@allowed([ + 'IdentityBased' + 'KeyBased' +]) +@description('Optional. Specifies the authentication type being used for connecting to the endpoint. If \'KeyBased\' is selected, a connection string must be specified (at least the primary connection string). If \'IdentityBased\' is selected, the endpointUri and entityPath properties must be specified.') +param authenticationType string = 'IdentityBased' + +@description('Optional. Dead letter storage secret for key-based authentication. Will be obfuscated during read.') +@secure() +param deadLetterSecret string = '' + +@description('Optional. Dead letter storage URL for identity-based authentication.') +param deadLetterUri string = '' + +@description('Conditional. PrimaryConnectionString of the endpoint for key-based authentication. Will be obfuscated during read. Required if the `authenticationType` is "KeyBased".') +@secure() +param connectionStringPrimaryKey string = '' + +@description('Optional. SecondaryConnectionString of the endpoint for key-based authentication. Will be obfuscated during read. Only used if the `authenticationType` is "KeyBased".') +@secure() +param connectionStringSecondaryKey string = '' + +@description('Optional. The EventHub name in the EventHub namespace for identity-based authentication.') +param entityPath string = '' + +@description('Optional. The URL of the EventHub namespace for identity-based authentication. It must include the protocol \'sb://\' (i.e. sb://xyz.servicebus.windows.net).') +param endpointUri string = '' + +var formattedUserAssignedIdentities = reduce(map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), {}, (cur, next) => union(cur, next)) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } + +@description('Optional. The managed identity definition for this resource.') +param managedIdentities managedIdentitiesType + +var identity = !empty(managedIdentities) ? { + type: (managedIdentities.?systemAssigned ?? false) ? (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : 'None') + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null +} : null + +resource digitalTwinsInstance 'Microsoft.DigitalTwins/digitalTwinsInstances@2023-01-31' existing = { + name: digitalTwinInstanceName +} + +resource endpoint 'Microsoft.DigitalTwins/digitalTwinsInstances/endpoints@2023-01-31' = { + name: name + parent: digitalTwinsInstance + properties: { + endpointType: 'EventHub' + authenticationType: authenticationType + connectionStringPrimaryKey: connectionStringPrimaryKey + connectionStringSecondaryKey: connectionStringSecondaryKey + deadLetterSecret: deadLetterSecret + deadLetterUri: deadLetterUri + endpointUri: endpointUri + entityPath: entityPath + identity: identity + } +} + +@description('The resource ID of the Endpoint.') +output resourceId string = endpoint.id + +@description('The name of the resource group the resource was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the Endpoint.') +output name string = endpoint.name + +@description('The principal ID of the system assigned identity.') +output systemAssignedMIPrincipalId string = endpoint.?identity.?principalId ?? '' + +// =============== // +// 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[]? +}? diff --git a/avm/res/digital-twins/digital-twins-instance/endpoint--event-hub/main.json b/avm/res/digital-twins/digital-twins-instance/endpoint--event-hub/main.json new file mode 100644 index 0000000000..7da5d6a4ce --- /dev/null +++ b/avm/res/digital-twins/digital-twins-instance/endpoint--event-hub/main.json @@ -0,0 +1,175 @@ +{ + "$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.26.54.24096", + "templateHash": "982830653292321499" + }, + "name": "Digital Twins Instance EventHub Endpoint", + "description": "This module deploys a Digital Twins Instance EventHub Endpoint.", + "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 + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "EventHubEndpoint", + "metadata": { + "description": "Optional. The name of the Digital Twin Endpoint." + } + }, + "digitalTwinInstanceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Digital Twin Instance resource. Required if the template is used in a standalone deployment." + } + }, + "authenticationType": { + "type": "string", + "defaultValue": "IdentityBased", + "allowedValues": [ + "IdentityBased", + "KeyBased" + ], + "metadata": { + "description": "Optional. Specifies the authentication type being used for connecting to the endpoint. If 'KeyBased' is selected, a connection string must be specified (at least the primary connection string). If 'IdentityBased' is selected, the endpointUri and entityPath properties must be specified." + } + }, + "deadLetterSecret": { + "type": "securestring", + "defaultValue": "", + "metadata": { + "description": "Optional. Dead letter storage secret for key-based authentication. Will be obfuscated during read." + } + }, + "deadLetterUri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Dead letter storage URL for identity-based authentication." + } + }, + "connectionStringPrimaryKey": { + "type": "securestring", + "defaultValue": "", + "metadata": { + "description": "Conditional. PrimaryConnectionString of the endpoint for key-based authentication. Will be obfuscated during read. Required if the `authenticationType` is \"KeyBased\"." + } + }, + "connectionStringSecondaryKey": { + "type": "securestring", + "defaultValue": "", + "metadata": { + "description": "Optional. SecondaryConnectionString of the endpoint for key-based authentication. Will be obfuscated during read. Only used if the `authenticationType` is \"KeyBased\"." + } + }, + "entityPath": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The EventHub name in the EventHub namespace for identity-based authentication." + } + }, + "endpointUri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The URL of the EventHub namespace for identity-based authentication. It must include the protocol 'sb://' (i.e. sb://xyz.servicebus.windows.net)." + } + }, + "managedIdentities": { + "$ref": "#/definitions/managedIdentitiesType", + "metadata": { + "description": "Optional. The managed identity definition for this resource." + } + } + }, + "variables": { + "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())]" + }, + "resources": { + "digitalTwinsInstance": { + "existing": true, + "type": "Microsoft.DigitalTwins/digitalTwinsInstances", + "apiVersion": "2023-01-31", + "name": "[parameters('digitalTwinInstanceName')]" + }, + "endpoint": { + "type": "Microsoft.DigitalTwins/digitalTwinsInstances/endpoints", + "apiVersion": "2023-01-31", + "name": "[format('{0}/{1}', parameters('digitalTwinInstanceName'), parameters('name'))]", + "properties": { + "endpointType": "EventHub", + "authenticationType": "[parameters('authenticationType')]", + "connectionStringPrimaryKey": "[parameters('connectionStringPrimaryKey')]", + "connectionStringSecondaryKey": "[parameters('connectionStringSecondaryKey')]", + "deadLetterSecret": "[parameters('deadLetterSecret')]", + "deadLetterUri": "[parameters('deadLetterUri')]", + "endpointUri": "[parameters('endpointUri')]", + "entityPath": "[parameters('entityPath')]", + "identity": "[variables('identity')]" + }, + "dependsOn": [ + "digitalTwinsInstance" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Endpoint." + }, + "value": "[resourceId('Microsoft.DigitalTwins/digitalTwinsInstances/endpoints', parameters('digitalTwinInstanceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the resource was created in." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the Endpoint." + }, + "value": "[parameters('name')]" + }, + "systemAssignedMIPrincipalId": { + "type": "string", + "metadata": { + "description": "The principal ID of the system assigned identity." + }, + "value": "[coalesce(tryGet(tryGet(reference('endpoint', '2023-01-31', 'full'), 'identity'), 'principalId'), '')]" + } + } +} \ No newline at end of file diff --git a/avm/res/digital-twins/digital-twins-instance/endpoint--service-bus/README.md b/avm/res/digital-twins/digital-twins-instance/endpoint--service-bus/README.md new file mode 100644 index 0000000000..2583883f1f --- /dev/null +++ b/avm/res/digital-twins/digital-twins-instance/endpoint--service-bus/README.md @@ -0,0 +1,163 @@ +# Digital Twins Instance ServiceBus Endpoint `[Microsoft.DigitalTwins/digitalTwinsInstances/endpoints]` + +This module deploys a Digital Twins Instance ServiceBus Endpoint. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.DigitalTwins/digitalTwinsInstances/endpoints` | [2023-01-31](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DigitalTwins/2023-01-31/digitalTwinsInstances/endpoints) | + +## Parameters + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`digitalTwinInstanceName`](#parameter-digitaltwininstancename) | string | The name of the parent Digital Twin Instance resource. Required if the template is used in a standalone deployment. | +| [`primaryConnectionString`](#parameter-primaryconnectionstring) | securestring | PrimaryConnectionString of the endpoint for key-based authentication. Will be obfuscated during read. Required if the `authenticationType` is "KeyBased". | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`authenticationType`](#parameter-authenticationtype) | string | Specifies the authentication type being used for connecting to the endpoint. If 'KeyBased' is selected, a connection string must be specified (at least the primary connection string). If 'IdentityBased' is selected, the endpointUri and entityPath properties must be specified. | +| [`deadLetterSecret`](#parameter-deadlettersecret) | securestring | Dead letter storage secret for key-based authentication. Will be obfuscated during read. | +| [`deadLetterUri`](#parameter-deadletteruri) | string | Dead letter storage URL for identity-based authentication. | +| [`endpointUri`](#parameter-endpointuri) | string | The URL of the ServiceBus namespace for identity-based authentication. It must include the protocol 'sb://' (e.g. sb://xyz.servicebus.windows.net). | +| [`entityPath`](#parameter-entitypath) | string | The ServiceBus Topic name for identity-based authentication. | +| [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. | +| [`name`](#parameter-name) | string | The name of the Digital Twin Endpoint. | +| [`secondaryConnectionString`](#parameter-secondaryconnectionstring) | securestring | SecondaryConnectionString of the endpoint for key-based authentication. Will be obfuscated during read. Only used if the `authenticationType` is "KeyBased". | + +### Parameter: `digitalTwinInstanceName` + +The name of the parent Digital Twin Instance resource. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `primaryConnectionString` + +PrimaryConnectionString of the endpoint for key-based authentication. Will be obfuscated during read. Required if the `authenticationType` is "KeyBased". + +- Required: No +- Type: securestring +- Default: `''` + +### Parameter: `authenticationType` + +Specifies the authentication type being used for connecting to the endpoint. If 'KeyBased' is selected, a connection string must be specified (at least the primary connection string). If 'IdentityBased' is selected, the endpointUri and entityPath properties must be specified. + +- Required: No +- Type: string +- Default: `'IdentityBased'` +- Allowed: + ```Bicep + [ + 'IdentityBased' + 'KeyBased' + ] + ``` + +### Parameter: `deadLetterSecret` + +Dead letter storage secret for key-based authentication. Will be obfuscated during read. + +- Required: No +- Type: securestring +- Default: `''` + +### Parameter: `deadLetterUri` + +Dead letter storage URL for identity-based authentication. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `endpointUri` + +The URL of the ServiceBus namespace for identity-based authentication. It must include the protocol 'sb://' (e.g. sb://xyz.servicebus.windows.net). + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `entityPath` + +The ServiceBus Topic name for identity-based authentication. + +- Required: No +- Type: string +- Default: `''` + +### 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. | + +### 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: No +- Type: array + +### Parameter: `name` + +The name of the Digital Twin Endpoint. + +- Required: No +- Type: string +- Default: `'ServiceBusEndpoint'` + +### Parameter: `secondaryConnectionString` + +SecondaryConnectionString of the endpoint for key-based authentication. Will be obfuscated during read. Only used if the `authenticationType` is "KeyBased". + +- Required: No +- Type: securestring +- Default: `''` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Endpoint. | +| `resourceGroupName` | string | The name of the resource group the resource was created in. | +| `resourceId` | string | The resource ID of the Endpoint. | +| `systemAssignedMIPrincipalId` | string | The principal ID of the system assigned identity. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/digital-twins/digital-twins-instance/endpoint--service-bus/main.bicep b/avm/res/digital-twins/digital-twins-instance/endpoint--service-bus/main.bicep new file mode 100644 index 0000000000..7d73f23373 --- /dev/null +++ b/avm/res/digital-twins/digital-twins-instance/endpoint--service-bus/main.bicep @@ -0,0 +1,92 @@ +metadata name = 'Digital Twins Instance ServiceBus Endpoint' +metadata description = 'This module deploys a Digital Twins Instance ServiceBus Endpoint.' +metadata owner = 'Azure/module-maintainers' + +@description('Optional. The name of the Digital Twin Endpoint.') +param name string = 'ServiceBusEndpoint' + +@description('Conditional. The name of the parent Digital Twin Instance resource. Required if the template is used in a standalone deployment.') +param digitalTwinInstanceName string + +@allowed([ + 'IdentityBased' + 'KeyBased' +]) +@description('Optional. Specifies the authentication type being used for connecting to the endpoint. If \'KeyBased\' is selected, a connection string must be specified (at least the primary connection string). If \'IdentityBased\' is selected, the endpointUri and entityPath properties must be specified.') +param authenticationType string = 'IdentityBased' + +@description('Optional. Dead letter storage secret for key-based authentication. Will be obfuscated during read.') +@secure() +param deadLetterSecret string = '' + +@description('Optional. Dead letter storage URL for identity-based authentication.') +param deadLetterUri string = '' + +@description('Optional. The URL of the ServiceBus namespace for identity-based authentication. It must include the protocol \'sb://\' (e.g. sb://xyz.servicebus.windows.net).') +param endpointUri string = '' + +@description('Optional. The ServiceBus Topic name for identity-based authentication.') +param entityPath string = '' + +@description('Conditional. PrimaryConnectionString of the endpoint for key-based authentication. Will be obfuscated during read. Required if the `authenticationType` is "KeyBased".') +@secure() +param primaryConnectionString string = '' + +@description('Optional. SecondaryConnectionString of the endpoint for key-based authentication. Will be obfuscated during read. Only used if the `authenticationType` is "KeyBased".') +@secure() +param secondaryConnectionString string = '' + +var formattedUserAssignedIdentities = reduce(map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), {}, (cur, next) => union(cur, next)) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } + +@description('Optional. The managed identity definition for this resource.') +param managedIdentities managedIdentitiesType + +var identity = !empty(managedIdentities) ? { + type: (managedIdentities.?systemAssigned ?? false) ? (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : 'None') + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null +} : null + +resource digitalTwinsInstance 'Microsoft.DigitalTwins/digitalTwinsInstances@2023-01-31' existing = { + name: digitalTwinInstanceName +} + +resource endpoint 'Microsoft.DigitalTwins/digitalTwinsInstances/endpoints@2023-01-31' = { + name: name + parent: digitalTwinsInstance + properties: { + endpointType: 'ServiceBus' + authenticationType: authenticationType + deadLetterSecret: deadLetterSecret + deadLetterUri: deadLetterUri + endpointUri: endpointUri + entityPath: entityPath + primaryConnectionString: primaryConnectionString + secondaryConnectionString: secondaryConnectionString + identity: identity + + } +} + +@description('The resource ID of the Endpoint.') +output resourceId string = endpoint.id + +@description('The name of the resource group the resource was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the Endpoint.') +output name string = endpoint.name + +@description('The principal ID of the system assigned identity.') +output systemAssignedMIPrincipalId string = endpoint.?identity.?principalId ?? '' + +// =============== // +// 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[]? +}? diff --git a/avm/res/digital-twins/digital-twins-instance/endpoint--service-bus/main.json b/avm/res/digital-twins/digital-twins-instance/endpoint--service-bus/main.json new file mode 100644 index 0000000000..52847cffed --- /dev/null +++ b/avm/res/digital-twins/digital-twins-instance/endpoint--service-bus/main.json @@ -0,0 +1,175 @@ +{ + "$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.26.54.24096", + "templateHash": "18420338400061008774" + }, + "name": "Digital Twins Instance ServiceBus Endpoint", + "description": "This module deploys a Digital Twins Instance ServiceBus Endpoint.", + "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 + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "ServiceBusEndpoint", + "metadata": { + "description": "Optional. The name of the Digital Twin Endpoint." + } + }, + "digitalTwinInstanceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Digital Twin Instance resource. Required if the template is used in a standalone deployment." + } + }, + "authenticationType": { + "type": "string", + "defaultValue": "IdentityBased", + "allowedValues": [ + "IdentityBased", + "KeyBased" + ], + "metadata": { + "description": "Optional. Specifies the authentication type being used for connecting to the endpoint. If 'KeyBased' is selected, a connection string must be specified (at least the primary connection string). If 'IdentityBased' is selected, the endpointUri and entityPath properties must be specified." + } + }, + "deadLetterSecret": { + "type": "securestring", + "defaultValue": "", + "metadata": { + "description": "Optional. Dead letter storage secret for key-based authentication. Will be obfuscated during read." + } + }, + "deadLetterUri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Dead letter storage URL for identity-based authentication." + } + }, + "endpointUri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The URL of the ServiceBus namespace for identity-based authentication. It must include the protocol 'sb://' (e.g. sb://xyz.servicebus.windows.net)." + } + }, + "entityPath": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The ServiceBus Topic name for identity-based authentication." + } + }, + "primaryConnectionString": { + "type": "securestring", + "defaultValue": "", + "metadata": { + "description": "Conditional. PrimaryConnectionString of the endpoint for key-based authentication. Will be obfuscated during read. Required if the `authenticationType` is \"KeyBased\"." + } + }, + "secondaryConnectionString": { + "type": "securestring", + "defaultValue": "", + "metadata": { + "description": "Optional. SecondaryConnectionString of the endpoint for key-based authentication. Will be obfuscated during read. Only used if the `authenticationType` is \"KeyBased\"." + } + }, + "managedIdentities": { + "$ref": "#/definitions/managedIdentitiesType", + "metadata": { + "description": "Optional. The managed identity definition for this resource." + } + } + }, + "variables": { + "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())]" + }, + "resources": { + "digitalTwinsInstance": { + "existing": true, + "type": "Microsoft.DigitalTwins/digitalTwinsInstances", + "apiVersion": "2023-01-31", + "name": "[parameters('digitalTwinInstanceName')]" + }, + "endpoint": { + "type": "Microsoft.DigitalTwins/digitalTwinsInstances/endpoints", + "apiVersion": "2023-01-31", + "name": "[format('{0}/{1}', parameters('digitalTwinInstanceName'), parameters('name'))]", + "properties": { + "endpointType": "ServiceBus", + "authenticationType": "[parameters('authenticationType')]", + "deadLetterSecret": "[parameters('deadLetterSecret')]", + "deadLetterUri": "[parameters('deadLetterUri')]", + "endpointUri": "[parameters('endpointUri')]", + "entityPath": "[parameters('entityPath')]", + "primaryConnectionString": "[parameters('primaryConnectionString')]", + "secondaryConnectionString": "[parameters('secondaryConnectionString')]", + "identity": "[variables('identity')]" + }, + "dependsOn": [ + "digitalTwinsInstance" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Endpoint." + }, + "value": "[resourceId('Microsoft.DigitalTwins/digitalTwinsInstances/endpoints', parameters('digitalTwinInstanceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the resource was created in." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the Endpoint." + }, + "value": "[parameters('name')]" + }, + "systemAssignedMIPrincipalId": { + "type": "string", + "metadata": { + "description": "The principal ID of the system assigned identity." + }, + "value": "[coalesce(tryGet(tryGet(reference('endpoint', '2023-01-31', 'full'), 'identity'), 'principalId'), '')]" + } + } +} \ No newline at end of file diff --git a/avm/res/digital-twins/digital-twins-instance/main.bicep b/avm/res/digital-twins/digital-twins-instance/main.bicep new file mode 100644 index 0000000000..2ad665a0fe --- /dev/null +++ b/avm/res/digital-twins/digital-twins-instance/main.bicep @@ -0,0 +1,408 @@ +metadata name = 'Digital Twins Instances' +metadata description = 'This module deploys an Azure Digital Twins Instance.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. The name of the Digital Twin Instance.') +@minLength(3) +@maxLength(63) +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Resource tags.') +param tags object? + +@description('Optional. The lock settings of the service.') +param lock lockType + +@description('Optional. The managed identity definition for this resource.') +param managedIdentities managedIdentitiesType + +@description('Optional. Event Hub Endpoint.') +param eventHubEndpoint object = {} + +@description('Optional. Event Grid Endpoint.') +param eventGridEndpoint object = {} + +@description('Optional. Service Bus Endpoint.') +param serviceBusEndpoint object = {} + +@description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') +param privateEndpoints privateEndpointType + +@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([ + '' + 'Enabled' + 'Disabled' +]) +param publicNetworkAccess string = '' + +@description('Optional. The diagnostic settings of the service.') +param diagnosticSettings diagnosticSettingType + +@description('Optional. Enable/Disable usage telemetry for module.') +param enableTelemetry bool = true + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalIds\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') +param roleAssignments roleAssignmentType + +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' : 'None') + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null +} : null + +var builtInRoleNames = { + 'Azure Digital Twins Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bcd981a7-7f74-457b-83e1-cceb9e632ffe') + 'Azure Digital Twins Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd57506d4-4c8d-48b1-8587-93c323f6a5a3') + 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.digitaltwins-digitaltwinsinstance.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } + } + } + } +} + +resource digitalTwinsInstance 'Microsoft.DigitalTwins/digitalTwinsInstances@2023-01-31' = { + name: name + location: location + identity: identity + tags: tags + properties: { + publicNetworkAccess: !empty(publicNetworkAccess) ? any(publicNetworkAccess) : (!empty(privateEndpoints) ? 'Disabled' : 'Enabled') + } +} + +module digitalTwinsInstance_eventHubEndpoint 'endpoint--event-hub/main.bicep' = if (!empty(eventHubEndpoint)) { + name: '${uniqueString(deployment().name, location)}-DigitalTwinsInstance-Endpoints-EventHub' + params: { + digitalTwinInstanceName: digitalTwinsInstance.name + name: contains(eventHubEndpoint, 'name') ? eventHubEndpoint.name : 'EventHubEndpoint' + authenticationType: contains(eventHubEndpoint, 'authenticationType') ? eventHubEndpoint.authenticationType : 'KeyBased' + connectionStringPrimaryKey: contains(eventHubEndpoint, 'connectionStringPrimaryKey') ? eventHubEndpoint.connectionStringPrimaryKey : '' + connectionStringSecondaryKey: contains(eventHubEndpoint, 'connectionStringSecondaryKey') ? eventHubEndpoint.connectionStringSecondaryKey : '' + deadLetterSecret: contains(eventHubEndpoint, 'deadLetterSecret') ? eventHubEndpoint.deadLetterSecret : '' + deadLetterUri: contains(eventHubEndpoint, 'deadLetterUri') ? eventHubEndpoint.deadLetterUri : '' + endpointUri: contains(eventHubEndpoint, 'endpointUri') ? eventHubEndpoint.endpointUri : '' + entityPath: contains(eventHubEndpoint, 'entityPath') ? eventHubEndpoint.entityPath : '' + managedIdentities: contains(eventHubEndpoint, 'managedIdentities') ? eventHubEndpoint.managedIdentities : {} + } +} + +module digitalTwinsInstance_eventGridEndpoint 'endpoint--event-grid/main.bicep' = if (!empty(eventGridEndpoint)) { + name: '${uniqueString(deployment().name, location)}-DigitalTwinsInstance-Endpoints-EventGrid' + params: { + digitalTwinInstanceName: digitalTwinsInstance.name + name: contains(eventGridEndpoint, 'name') ? eventGridEndpoint.name : 'EventGridEndpoint' + topicEndpoint: contains(eventGridEndpoint, 'topicEndpoint') ? eventGridEndpoint.topicEndpoint : '' + deadLetterSecret: contains(eventGridEndpoint, 'deadLetterSecret') ? eventGridEndpoint.deadLetterSecret : '' + deadLetterUri: contains(eventGridEndpoint, 'deadLetterUri') ? eventGridEndpoint.deadLetterUri : '' + eventGridDomainResourceId: contains(eventGridEndpoint, 'eventGridDomainId') ? eventGridEndpoint.eventGridDomainId : '' + } +} + +module digitalTwinsInstance_serviceBusEndpoint 'endpoint--service-bus/main.bicep' = if (!empty(serviceBusEndpoint)) { + name: '${uniqueString(deployment().name, location)}-DigitalTwinsInstance-Endpoints-ServiceBus' + params: { + digitalTwinInstanceName: digitalTwinsInstance.name + name: contains(serviceBusEndpoint, 'name') ? serviceBusEndpoint.name : 'ServiceBusEndpoint' + authenticationType: contains(serviceBusEndpoint, 'authenticationType') ? serviceBusEndpoint.authenticationType : '' + deadLetterSecret: contains(serviceBusEndpoint, 'deadLetterSecret') ? serviceBusEndpoint.deadLetterSecret : '' + deadLetterUri: contains(serviceBusEndpoint, 'deadLetterUri') ? serviceBusEndpoint.deadLetterUri : '' + endpointUri: contains(serviceBusEndpoint, 'endpointUri') ? serviceBusEndpoint.endpointUri : '' + entityPath: contains(serviceBusEndpoint, 'entityPath') ? serviceBusEndpoint.entityPath : '' + primaryConnectionString: contains(serviceBusEndpoint, 'primaryConnectionString') ? serviceBusEndpoint.primaryConnectionString : '' + secondaryConnectionString: contains(serviceBusEndpoint, 'secondaryConnectionString') ? serviceBusEndpoint.secondaryConnectionString : '' + managedIdentities: contains(serviceBusEndpoint, 'managedIdentities') ? serviceBusEndpoint.managedIdentities : {} + } +} + +module digitalTwinsInstance_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-DigitalTwinsInstance-PrivateEndpoint-${index}' + scope: resourceGroup(privateEndpoint.?resourceGroupName ?? '') + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(digitalTwinsInstance.id, '/'))}-${privateEndpoint.?service ?? 'API'}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(digitalTwinsInstance.id, '/'))}-${privateEndpoint.?service ?? 'API'}-${index}' + properties: { + privateLinkServiceId: digitalTwinsInstance.id + groupIds: [ + privateEndpoint.?service ?? 'API' + ] + } + } + ] : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(digitalTwinsInstance.id, '/'))}-${privateEndpoint.?service ?? 'API'}-${index}' + properties: { + privateLinkServiceId: digitalTwinsInstance.id + groupIds: [ + privateEndpoint.?service ?? 'API' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } + ] : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } +}] + +resource digitalTwinsInstance_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: digitalTwinsInstance +} + +resource digitalTwinsInstance_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + }] + logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + }] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: digitalTwinsInstance +}] + +resource digitalTwinsInstance_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(digitalTwinsInstance.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: digitalTwinsInstance +}] + +@description('The resource ID of the Digital Twins Instance.') +output resourceId string = digitalTwinsInstance.id + +@description('The name of the resource group the resource was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the Digital Twins Instance.') +output name string = digitalTwinsInstance.name + +@description('The hostname of the Digital Twins Instance.') +output hostname string = digitalTwinsInstance.properties.hostName + +@description('The location the resource was deployed into.') +output location string = digitalTwinsInstance.location + +@description('The principal ID of the system assigned identity.') +output systemAssignedMIPrincipalId string = digitalTwinsInstance.?identity.?principalId ?? '' + +// =============== // +// 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('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 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 Privte 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/digital-twins/digital-twins-instance/main.json b/avm/res/digital-twins/digital-twins-instance/main.json new file mode 100644 index 0000000000..b845ff6813 --- /dev/null +++ b/avm/res/digital-twins/digital-twins-instance/main.json @@ -0,0 +1,1891 @@ +{ + "$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.26.54.24096", + "templateHash": "5068998297960417598" + }, + "name": "Digital Twins Instances", + "description": "This module deploys an Azure Digital Twins Instance.", + "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": { + "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." + } + }, + "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 Privte 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 + } + }, + "parameters": { + "name": { + "type": "string", + "minLength": 3, + "maxLength": 63, + "metadata": { + "description": "Required. The name of the Digital Twin Instance." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "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." + } + }, + "eventHubEndpoint": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Event Hub Endpoint." + } + }, + "eventGridEndpoint": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Event Grid Endpoint." + } + }, + "serviceBusEndpoint": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Service Bus Endpoint." + } + }, + "privateEndpoints": { + "$ref": "#/definitions/privateEndpointType", + "metadata": { + "description": "Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible." + } + }, + "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." + } + }, + "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." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalIds' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + } + }, + "variables": { + "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 Digital Twins Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bcd981a7-7f74-457b-83e1-cceb9e632ffe')]", + "Azure Digital Twins Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd57506d4-4c8d-48b1-8587-93c323f6a5a3')]", + "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 (Preview)": "[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": "2023-07-01", + "name": "[format('46d3xbcp.res.digitaltwins-digitaltwinsinstance.{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" + } + } + } + } + }, + "digitalTwinsInstance": { + "type": "Microsoft.DigitalTwins/digitalTwinsInstances", + "apiVersion": "2023-01-31", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "identity": "[variables('identity')]", + "tags": "[parameters('tags')]", + "properties": { + "publicNetworkAccess": "[if(not(empty(parameters('publicNetworkAccess'))), parameters('publicNetworkAccess'), if(not(empty(parameters('privateEndpoints'))), 'Disabled', 'Enabled'))]" + } + }, + "digitalTwinsInstance_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.DigitalTwins/digitalTwinsInstances/{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": [ + "digitalTwinsInstance" + ] + }, + "digitalTwinsInstance_diagnosticSettings": { + "copy": { + "name": "digitalTwinsInstance_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.DigitalTwins/digitalTwinsInstances/{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": [ + "digitalTwinsInstance" + ] + }, + "digitalTwinsInstance_roleAssignments": { + "copy": { + "name": "digitalTwinsInstance_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.DigitalTwins/digitalTwinsInstances/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.DigitalTwins/digitalTwinsInstances', 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": [ + "digitalTwinsInstance" + ] + }, + "digitalTwinsInstance_eventHubEndpoint": { + "condition": "[not(empty(parameters('eventHubEndpoint')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-DigitalTwinsInstance-Endpoints-EventHub', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "digitalTwinInstanceName": { + "value": "[parameters('name')]" + }, + "name": "[if(contains(parameters('eventHubEndpoint'), 'name'), createObject('value', parameters('eventHubEndpoint').name), createObject('value', 'EventHubEndpoint'))]", + "authenticationType": "[if(contains(parameters('eventHubEndpoint'), 'authenticationType'), createObject('value', parameters('eventHubEndpoint').authenticationType), createObject('value', 'KeyBased'))]", + "connectionStringPrimaryKey": "[if(contains(parameters('eventHubEndpoint'), 'connectionStringPrimaryKey'), createObject('value', parameters('eventHubEndpoint').connectionStringPrimaryKey), createObject('value', ''))]", + "connectionStringSecondaryKey": "[if(contains(parameters('eventHubEndpoint'), 'connectionStringSecondaryKey'), createObject('value', parameters('eventHubEndpoint').connectionStringSecondaryKey), createObject('value', ''))]", + "deadLetterSecret": "[if(contains(parameters('eventHubEndpoint'), 'deadLetterSecret'), createObject('value', parameters('eventHubEndpoint').deadLetterSecret), createObject('value', ''))]", + "deadLetterUri": "[if(contains(parameters('eventHubEndpoint'), 'deadLetterUri'), createObject('value', parameters('eventHubEndpoint').deadLetterUri), createObject('value', ''))]", + "endpointUri": "[if(contains(parameters('eventHubEndpoint'), 'endpointUri'), createObject('value', parameters('eventHubEndpoint').endpointUri), createObject('value', ''))]", + "entityPath": "[if(contains(parameters('eventHubEndpoint'), 'entityPath'), createObject('value', parameters('eventHubEndpoint').entityPath), createObject('value', ''))]", + "managedIdentities": "[if(contains(parameters('eventHubEndpoint'), 'managedIdentities'), createObject('value', parameters('eventHubEndpoint').managedIdentities), createObject('value', createObject()))]" + }, + "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.26.54.24096", + "templateHash": "982830653292321499" + }, + "name": "Digital Twins Instance EventHub Endpoint", + "description": "This module deploys a Digital Twins Instance EventHub Endpoint.", + "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 + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "EventHubEndpoint", + "metadata": { + "description": "Optional. The name of the Digital Twin Endpoint." + } + }, + "digitalTwinInstanceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Digital Twin Instance resource. Required if the template is used in a standalone deployment." + } + }, + "authenticationType": { + "type": "string", + "defaultValue": "IdentityBased", + "allowedValues": [ + "IdentityBased", + "KeyBased" + ], + "metadata": { + "description": "Optional. Specifies the authentication type being used for connecting to the endpoint. If 'KeyBased' is selected, a connection string must be specified (at least the primary connection string). If 'IdentityBased' is selected, the endpointUri and entityPath properties must be specified." + } + }, + "deadLetterSecret": { + "type": "securestring", + "defaultValue": "", + "metadata": { + "description": "Optional. Dead letter storage secret for key-based authentication. Will be obfuscated during read." + } + }, + "deadLetterUri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Dead letter storage URL for identity-based authentication." + } + }, + "connectionStringPrimaryKey": { + "type": "securestring", + "defaultValue": "", + "metadata": { + "description": "Conditional. PrimaryConnectionString of the endpoint for key-based authentication. Will be obfuscated during read. Required if the `authenticationType` is \"KeyBased\"." + } + }, + "connectionStringSecondaryKey": { + "type": "securestring", + "defaultValue": "", + "metadata": { + "description": "Optional. SecondaryConnectionString of the endpoint for key-based authentication. Will be obfuscated during read. Only used if the `authenticationType` is \"KeyBased\"." + } + }, + "entityPath": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The EventHub name in the EventHub namespace for identity-based authentication." + } + }, + "endpointUri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The URL of the EventHub namespace for identity-based authentication. It must include the protocol 'sb://' (i.e. sb://xyz.servicebus.windows.net)." + } + }, + "managedIdentities": { + "$ref": "#/definitions/managedIdentitiesType", + "metadata": { + "description": "Optional. The managed identity definition for this resource." + } + } + }, + "variables": { + "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())]" + }, + "resources": { + "digitalTwinsInstance": { + "existing": true, + "type": "Microsoft.DigitalTwins/digitalTwinsInstances", + "apiVersion": "2023-01-31", + "name": "[parameters('digitalTwinInstanceName')]" + }, + "endpoint": { + "type": "Microsoft.DigitalTwins/digitalTwinsInstances/endpoints", + "apiVersion": "2023-01-31", + "name": "[format('{0}/{1}', parameters('digitalTwinInstanceName'), parameters('name'))]", + "properties": { + "endpointType": "EventHub", + "authenticationType": "[parameters('authenticationType')]", + "connectionStringPrimaryKey": "[parameters('connectionStringPrimaryKey')]", + "connectionStringSecondaryKey": "[parameters('connectionStringSecondaryKey')]", + "deadLetterSecret": "[parameters('deadLetterSecret')]", + "deadLetterUri": "[parameters('deadLetterUri')]", + "endpointUri": "[parameters('endpointUri')]", + "entityPath": "[parameters('entityPath')]", + "identity": "[variables('identity')]" + }, + "dependsOn": [ + "digitalTwinsInstance" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Endpoint." + }, + "value": "[resourceId('Microsoft.DigitalTwins/digitalTwinsInstances/endpoints', parameters('digitalTwinInstanceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the resource was created in." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the Endpoint." + }, + "value": "[parameters('name')]" + }, + "systemAssignedMIPrincipalId": { + "type": "string", + "metadata": { + "description": "The principal ID of the system assigned identity." + }, + "value": "[coalesce(tryGet(tryGet(reference('endpoint', '2023-01-31', 'full'), 'identity'), 'principalId'), '')]" + } + } + } + }, + "dependsOn": [ + "digitalTwinsInstance" + ] + }, + "digitalTwinsInstance_eventGridEndpoint": { + "condition": "[not(empty(parameters('eventGridEndpoint')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-DigitalTwinsInstance-Endpoints-EventGrid', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "digitalTwinInstanceName": { + "value": "[parameters('name')]" + }, + "name": "[if(contains(parameters('eventGridEndpoint'), 'name'), createObject('value', parameters('eventGridEndpoint').name), createObject('value', 'EventGridEndpoint'))]", + "topicEndpoint": "[if(contains(parameters('eventGridEndpoint'), 'topicEndpoint'), createObject('value', parameters('eventGridEndpoint').topicEndpoint), createObject('value', ''))]", + "deadLetterSecret": "[if(contains(parameters('eventGridEndpoint'), 'deadLetterSecret'), createObject('value', parameters('eventGridEndpoint').deadLetterSecret), createObject('value', ''))]", + "deadLetterUri": "[if(contains(parameters('eventGridEndpoint'), 'deadLetterUri'), createObject('value', parameters('eventGridEndpoint').deadLetterUri), createObject('value', ''))]", + "eventGridDomainResourceId": "[if(contains(parameters('eventGridEndpoint'), 'eventGridDomainId'), createObject('value', parameters('eventGridEndpoint').eventGridDomainId), createObject('value', ''))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.26.54.24096", + "templateHash": "11981298053277690078" + }, + "name": "Digital Twins Instance Event Grid Endpoints", + "description": "This module deploys a Digital Twins Instance Event Grid Endpoint.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "EventGridEndpoint", + "metadata": { + "description": "Optional. The name of the Digital Twin Endpoint." + } + }, + "digitalTwinInstanceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Digital Twin Instance resource. Required if the template is used in a standalone deployment." + } + }, + "topicEndpoint": { + "type": "string", + "metadata": { + "description": "Required. EventGrid Topic Endpoint." + } + }, + "eventGridDomainResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the Event Grid to get access keys from." + } + }, + "deadLetterSecret": { + "type": "securestring", + "defaultValue": "", + "metadata": { + "description": "Optional. Dead letter storage secret for key-based authentication. Will be obfuscated during read." + } + }, + "deadLetterUri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Dead letter storage URL for identity-based authentication." + } + } + }, + "resources": [ + { + "type": "Microsoft.DigitalTwins/digitalTwinsInstances/endpoints", + "apiVersion": "2023-01-31", + "name": "[format('{0}/{1}', parameters('digitalTwinInstanceName'), parameters('name'))]", + "properties": { + "endpointType": "EventGrid", + "authenticationType": "KeyBased", + "TopicEndpoint": "[parameters('topicEndpoint')]", + "accessKey1": "[listkeys(parameters('eventGridDomainResourceId'), '2022-06-15').key1]", + "accessKey2": "[listkeys(parameters('eventGridDomainResourceId'), '2022-06-15').key2]", + "deadLetterSecret": "[parameters('deadLetterSecret')]", + "deadLetterUri": "[parameters('deadLetterUri')]" + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Endpoint." + }, + "value": "[resourceId('Microsoft.DigitalTwins/digitalTwinsInstances/endpoints', parameters('digitalTwinInstanceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the resource was created in." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the Endpoint." + }, + "value": "[parameters('name')]" + } + } + } + }, + "dependsOn": [ + "digitalTwinsInstance" + ] + }, + "digitalTwinsInstance_serviceBusEndpoint": { + "condition": "[not(empty(parameters('serviceBusEndpoint')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-DigitalTwinsInstance-Endpoints-ServiceBus', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "digitalTwinInstanceName": { + "value": "[parameters('name')]" + }, + "name": "[if(contains(parameters('serviceBusEndpoint'), 'name'), createObject('value', parameters('serviceBusEndpoint').name), createObject('value', 'ServiceBusEndpoint'))]", + "authenticationType": "[if(contains(parameters('serviceBusEndpoint'), 'authenticationType'), createObject('value', parameters('serviceBusEndpoint').authenticationType), createObject('value', ''))]", + "deadLetterSecret": "[if(contains(parameters('serviceBusEndpoint'), 'deadLetterSecret'), createObject('value', parameters('serviceBusEndpoint').deadLetterSecret), createObject('value', ''))]", + "deadLetterUri": "[if(contains(parameters('serviceBusEndpoint'), 'deadLetterUri'), createObject('value', parameters('serviceBusEndpoint').deadLetterUri), createObject('value', ''))]", + "endpointUri": "[if(contains(parameters('serviceBusEndpoint'), 'endpointUri'), createObject('value', parameters('serviceBusEndpoint').endpointUri), createObject('value', ''))]", + "entityPath": "[if(contains(parameters('serviceBusEndpoint'), 'entityPath'), createObject('value', parameters('serviceBusEndpoint').entityPath), createObject('value', ''))]", + "primaryConnectionString": "[if(contains(parameters('serviceBusEndpoint'), 'primaryConnectionString'), createObject('value', parameters('serviceBusEndpoint').primaryConnectionString), createObject('value', ''))]", + "secondaryConnectionString": "[if(contains(parameters('serviceBusEndpoint'), 'secondaryConnectionString'), createObject('value', parameters('serviceBusEndpoint').secondaryConnectionString), createObject('value', ''))]", + "managedIdentities": "[if(contains(parameters('serviceBusEndpoint'), 'managedIdentities'), createObject('value', parameters('serviceBusEndpoint').managedIdentities), createObject('value', createObject()))]" + }, + "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.26.54.24096", + "templateHash": "18420338400061008774" + }, + "name": "Digital Twins Instance ServiceBus Endpoint", + "description": "This module deploys a Digital Twins Instance ServiceBus Endpoint.", + "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 + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "ServiceBusEndpoint", + "metadata": { + "description": "Optional. The name of the Digital Twin Endpoint." + } + }, + "digitalTwinInstanceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Digital Twin Instance resource. Required if the template is used in a standalone deployment." + } + }, + "authenticationType": { + "type": "string", + "defaultValue": "IdentityBased", + "allowedValues": [ + "IdentityBased", + "KeyBased" + ], + "metadata": { + "description": "Optional. Specifies the authentication type being used for connecting to the endpoint. If 'KeyBased' is selected, a connection string must be specified (at least the primary connection string). If 'IdentityBased' is selected, the endpointUri and entityPath properties must be specified." + } + }, + "deadLetterSecret": { + "type": "securestring", + "defaultValue": "", + "metadata": { + "description": "Optional. Dead letter storage secret for key-based authentication. Will be obfuscated during read." + } + }, + "deadLetterUri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Dead letter storage URL for identity-based authentication." + } + }, + "endpointUri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The URL of the ServiceBus namespace for identity-based authentication. It must include the protocol 'sb://' (e.g. sb://xyz.servicebus.windows.net)." + } + }, + "entityPath": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The ServiceBus Topic name for identity-based authentication." + } + }, + "primaryConnectionString": { + "type": "securestring", + "defaultValue": "", + "metadata": { + "description": "Conditional. PrimaryConnectionString of the endpoint for key-based authentication. Will be obfuscated during read. Required if the `authenticationType` is \"KeyBased\"." + } + }, + "secondaryConnectionString": { + "type": "securestring", + "defaultValue": "", + "metadata": { + "description": "Optional. SecondaryConnectionString of the endpoint for key-based authentication. Will be obfuscated during read. Only used if the `authenticationType` is \"KeyBased\"." + } + }, + "managedIdentities": { + "$ref": "#/definitions/managedIdentitiesType", + "metadata": { + "description": "Optional. The managed identity definition for this resource." + } + } + }, + "variables": { + "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())]" + }, + "resources": { + "digitalTwinsInstance": { + "existing": true, + "type": "Microsoft.DigitalTwins/digitalTwinsInstances", + "apiVersion": "2023-01-31", + "name": "[parameters('digitalTwinInstanceName')]" + }, + "endpoint": { + "type": "Microsoft.DigitalTwins/digitalTwinsInstances/endpoints", + "apiVersion": "2023-01-31", + "name": "[format('{0}/{1}', parameters('digitalTwinInstanceName'), parameters('name'))]", + "properties": { + "endpointType": "ServiceBus", + "authenticationType": "[parameters('authenticationType')]", + "deadLetterSecret": "[parameters('deadLetterSecret')]", + "deadLetterUri": "[parameters('deadLetterUri')]", + "endpointUri": "[parameters('endpointUri')]", + "entityPath": "[parameters('entityPath')]", + "primaryConnectionString": "[parameters('primaryConnectionString')]", + "secondaryConnectionString": "[parameters('secondaryConnectionString')]", + "identity": "[variables('identity')]" + }, + "dependsOn": [ + "digitalTwinsInstance" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Endpoint." + }, + "value": "[resourceId('Microsoft.DigitalTwins/digitalTwinsInstances/endpoints', parameters('digitalTwinInstanceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the resource was created in." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the Endpoint." + }, + "value": "[parameters('name')]" + }, + "systemAssignedMIPrincipalId": { + "type": "string", + "metadata": { + "description": "The principal ID of the system assigned identity." + }, + "value": "[coalesce(tryGet(tryGet(reference('endpoint', '2023-01-31', 'full'), 'identity'), 'principalId'), '')]" + } + } + } + }, + "dependsOn": [ + "digitalTwinsInstance" + ] + }, + "digitalTwinsInstance_privateEndpoints": { + "copy": { + "name": "digitalTwinsInstance_privateEndpoints", + "count": "[length(coalesce(parameters('privateEndpoints'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-DigitalTwinsInstance-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.DigitalTwins/digitalTwinsInstances', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'API'), copyIndex()))]" + }, + "privateLinkServiceConnections": "[if(not(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections'), true())), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.DigitalTwins/digitalTwinsInstances', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'API'), copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.DigitalTwins/digitalTwinsInstances', parameters('name')), 'groupIds', createArray(coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'API')))))), createObject('value', null()))]", + "manualPrivateLinkServiceConnections": "[if(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections'), true()), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.DigitalTwins/digitalTwinsInstances', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'API'), copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.DigitalTwins/digitalTwinsInstances', parameters('name')), 'groupIds', createArray(coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'API')), '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'))]" + }, + "privateDnsZoneGroupName": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneGroupName')]" + }, + "privateDnsZoneResourceIds": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneResourceIds')]" + }, + "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.24.24.22086", + "templateHash": "2592884001616184297" + }, + "name": "Private Endpoints", + "description": "This module deploys a Private Endpoint.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "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." + } + }, + "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 + }, + "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", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "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", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "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 + } + }, + "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." + } + }, + "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", + "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." + } + }, + "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": { + "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": "2023-07-01", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.4.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" + } + } + } + } + }, + "privateEndpoint": { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-04-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(parameters('roleAssignments'), 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)]", + "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": [ + "privateEndpoint" + ] + }, + "privateEndpoint_privateDnsZoneGroup": { + "condition": "[not(empty(parameters('privateDnsZoneResourceIds')))]", + "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": "[coalesce(parameters('privateDnsZoneGroupName'), 'default')]" + }, + "privateDNSResourceIds": { + "value": "[coalesce(parameters('privateDnsZoneResourceIds'), createArray())]" + }, + "privateEndpointName": { + "value": "[parameters('name')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "9321937464667207030" + }, + "name": "Private Endpoint Private DNS Zone Groups", + "description": "This module deploys a Private Endpoint Private DNS Zone Group.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "privateEndpointName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent private endpoint. Required if the template is used in a standalone deployment." + } + }, + "privateDNSResourceIds": { + "type": "array", + "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." + } + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the private DNS zone group." + } + } + }, + "variables": { + "copy": [ + { + "name": "privateDnsZoneConfigs", + "count": "[length(parameters('privateDNSResourceIds'))]", + "input": { + "name": "[last(split(parameters('privateDNSResourceIds')[copyIndex('privateDnsZoneConfigs')], '/'))]", + "properties": { + "privateDnsZoneId": "[parameters('privateDNSResourceIds')[copyIndex('privateDnsZoneConfigs')]]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2023-04-01", + "name": "[format('{0}/{1}', parameters('privateEndpointName'), parameters('name'))]", + "properties": { + "privateDnsZoneConfigs": "[variables('privateDnsZoneConfigs')]" + } + } + ], + "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-04-01', 'full').location]" + }, + "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])]" + } + } + } + }, + "dependsOn": [ + "digitalTwinsInstance" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Digital Twins Instance." + }, + "value": "[resourceId('Microsoft.DigitalTwins/digitalTwinsInstances', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the resource was created in." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the Digital Twins Instance." + }, + "value": "[parameters('name')]" + }, + "hostname": { + "type": "string", + "metadata": { + "description": "The hostname of the Digital Twins Instance." + }, + "value": "[reference('digitalTwinsInstance').hostName]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('digitalTwinsInstance', '2023-01-31', 'full').location]" + }, + "systemAssignedMIPrincipalId": { + "type": "string", + "metadata": { + "description": "The principal ID of the system assigned identity." + }, + "value": "[coalesce(tryGet(tryGet(reference('digitalTwinsInstance', '2023-01-31', 'full'), 'identity'), 'principalId'), '')]" + } + } +} \ No newline at end of file diff --git a/avm/res/digital-twins/digital-twins-instance/tests/e2e/defaults/main.test.bicep b/avm/res/digital-twins/digital-twins-instance/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..bcbf4637ac --- /dev/null +++ b/avm/res/digital-twins/digital-twins-instance/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,45 @@ +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}-digitaltwins.digitaltwinsinstances-${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 = 'dtdtimin' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +// ============== // +// 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' + } +}] diff --git a/avm/res/digital-twins/digital-twins-instance/tests/e2e/max/dependencies.bicep b/avm/res/digital-twins/digital-twins-instance/tests/e2e/max/dependencies.bicep new file mode 100644 index 0000000000..41387dda50 --- /dev/null +++ b/avm/res/digital-twins/digital-twins-instance/tests/e2e/max/dependencies.bicep @@ -0,0 +1,162 @@ +@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 + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +@description('Required. The name of the Event Hub Namespace to create.') +param eventHubNamespaceName string + +@description('Required. The name of the Event Hub to create.') +param eventHubName string + +@description('Required. Service Bus name') +param serviceBusName string + +@description('Required. Event Grid Domain name.') +param eventGridDomainName string + +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) + serviceEndpoints: [ + { + service: 'Microsoft.KeyVault' + } + ] + } + } + ] + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { + name: 'privatelink.digitaltwins.azure.net' + location: 'global' + + resource virtualNetworkLinks 'virtualNetworkLinks@2020-06-01' = { + name: '${virtualNetwork.name}-vnetlink' + location: 'global' + properties: { + virtualNetwork: { + id: virtualNetwork.id + } + registrationEnabled: false + } + } +} + +resource eventHubNamespace 'Microsoft.EventHub/namespaces@2022-10-01-preview' = { + name: eventHubNamespaceName + location: location + properties: { + zoneRedundant: false + isAutoInflateEnabled: false + maximumThroughputUnits: 0 + } + + resource eventHub 'eventhubs@2022-10-01-preview' = { + name: eventHubName + } +} + +resource serviceBus 'Microsoft.ServiceBus/namespaces@2022-10-01-preview' = { + name: serviceBusName + location: location + properties: { + zoneRedundant: false + } + + resource topic 'topics@2022-10-01-preview' = { + name: 'topic' + } +} + +resource eventGridDomain 'Microsoft.EventGrid/domains@2022-06-15' = { + name: eventGridDomainName + location: location + properties: { + disableLocalAuth: false + } + + resource topic 'topics@2022-06-15' = { + name: 'topic' + } +} + +resource eventHubNamespaceRbacAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(managedIdentity.id, 'evhrbacAssignment') + scope: eventHubNamespace + properties: { + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2b629674-e913-4c01-ae53-ef4638d8f975') //Azure Event Hubs Data Sender + principalId: managedIdentity.properties.principalId + principalType: 'ServicePrincipal' + } +} + +resource serviceBusRbacAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(managedIdentity.id, 'sbrbacAssignment') + scope: serviceBus + properties: { + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39') //Azure Service Bus Data Sender + principalId: managedIdentity.properties.principalId + principalType: 'ServicePrincipal' + } +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId + +@description('The resource ID of the created Private DNS Zone.') +output privateDNSZoneResourceId string = privateDNSZone.id + +@description('The name of the Event Hub Namespace.') +output eventhubNamespaceName string = eventHubNamespace.name + +@description('The resource ID of the created Event Hub Namespace.') +output eventHubResourceId string = eventHubNamespace::eventHub.id + +@description('The name of the Event Hub.') +output eventhubName string = eventHubNamespace::eventHub.name + +@description('The name of the Service Bus Namespace.') +output serviceBusName string = serviceBus.name + +@description('The name of the Service Bus Topic.') +output serviceBusTopicName string = serviceBus::topic.name + +@description('The Event Grid endpoint uri.') +output eventGridEndpoint string = eventGridDomain.properties.endpoint + +@description('The resource ID of the created Event Grid Topic.') +output eventGridTopicResourceId string = eventGridDomain::topic.id + +@description('The resource ID of the created Event Grid Domain.') +output eventGridDomainResourceId string = eventGridDomain.id + +@description('The resource ID of the created Managed Identity.') +output managedIdentityResourceId string = managedIdentity.id diff --git a/avm/res/digital-twins/digital-twins-instance/tests/e2e/max/main.test.bicep b/avm/res/digital-twins/digital-twins-instance/tests/e2e/max/main.test.bicep new file mode 100644 index 0000000000..4fcd43e149 --- /dev/null +++ b/avm/res/digital-twins/digital-twins-instance/tests/e2e/max/main.test.bicep @@ -0,0 +1,152 @@ +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}-digitaltwins.digitaltwinsinstances-${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 = 'dtdtimax' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + location: resourceLocation + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + eventHubName: 'dt-${uniqueString(serviceShort)}-evh-01' + eventHubNamespaceName: 'dt-${uniqueString(serviceShort)}-evhns-01' + serviceBusName: 'dt-${uniqueString(serviceShort)}-sb-01' + eventGridDomainName: 'dt-${uniqueString(serviceShort)}-evg-01' + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-diagnosticDependencies' + params: { + storageAccountName: 'dep${namePrefix}diasa${serviceShort}03' + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-${uniqueString(serviceShort)}-evh-01' + eventHubNamespaceName: 'dep-${uniqueString(serviceShort)}-evh-01' + 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: { + location: resourceLocation + eventHubEndpoint: { + authenticationType: 'IdentityBased' + endpointUri: 'sb://${nestedDependencies.outputs.eventhubNamespaceName}.servicebus.windows.net/' + entityPath: nestedDependencies.outputs.eventhubName + managedIdentities: { + userAssignedResourceId: nestedDependencies.outputs.managedIdentityResourceId + } + } + serviceBusEndpoint: { + authenticationType: 'IdentityBased' + endpointUri: 'sb://${nestedDependencies.outputs.serviceBusName}.servicebus.windows.net/' + entityPath: nestedDependencies.outputs.serviceBusTopicName + managedIdentities: { + userAssignedResourceId: nestedDependencies.outputs.managedIdentityResourceId + } + } + eventGridEndpoint: { + eventGridDomainId: nestedDependencies.outputs.eventGridDomainResourceId + topicEndpoint: nestedDependencies.outputs.eventGridEndpoint + } + name: '${namePrefix}${serviceShort}001' + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] +}] diff --git a/avm/res/digital-twins/digital-twins-instance/tests/e2e/pe/dependencies.bicep b/avm/res/digital-twins/digital-twins-instance/tests/e2e/pe/dependencies.bicep new file mode 100644 index 0000000000..1b34a4ac45 --- /dev/null +++ b/avm/res/digital-twins/digital-twins-instance/tests/e2e/pe/dependencies.bicep @@ -0,0 +1,68 @@ +@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@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 24, 0) + serviceEndpoints: [ + { + service: 'Microsoft.KeyVault' + } + ] + } + } + { + name: 'peTestSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 24, 1) + serviceEndpoints: [ + { + service: 'Microsoft.KeyVault' + } + ] + } + } + ] + } +} + +resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { + name: 'privatelink.digitaltwins.azure.net' + location: 'global' + + resource virtualNetworkLinks 'virtualNetworkLinks@2020-06-01' = { + name: '${virtualNetwork.name}-vnetlink' + location: 'global' + properties: { + virtualNetwork: { + id: virtualNetwork.id + } + registrationEnabled: false + } + } +} + +@description('The resource ID of the created Virtual Network Subnet.') +output defaultSubnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The resource ID of the created Virtual Network Subnet.') +output pepTestSubnetResourceId string = virtualNetwork.properties.subnets[1].id + +@description('The resource ID of the created Private DNS Zone.') +output privateDNSZoneResourceId string = privateDNSZone.id diff --git a/avm/res/digital-twins/digital-twins-instance/tests/e2e/pe/main.test.bicep b/avm/res/digital-twins/digital-twins-instance/tests/e2e/pe/main.test.bicep new file mode 100644 index 0000000000..7e1e67efda --- /dev/null +++ b/avm/res/digital-twins/digital-twins-instance/tests/e2e/pe/main.test.bicep @@ -0,0 +1,72 @@ +targetScope = 'subscription' + +metadata name = 'Using private endpoint parameter set' +metadata description = 'This instance deploys the module with idempotancy tests for private endpoints.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-digitaltwins.digitaltwinsinstances-${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 = 'dtdtipep' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + location: resourceLocation + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.defaultSubnetResourceId + } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.pepTestSubnetResourceId + } + ] + } + dependsOn: [ + nestedDependencies + ] +}] diff --git a/avm/res/digital-twins/digital-twins-instance/tests/e2e/waf-aligned/main.test.bicep b/avm/res/digital-twins/digital-twins-instance/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..ce1cc5197b --- /dev/null +++ b/avm/res/digital-twins/digital-twins-instance/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,76 @@ +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}-digitaltwins.digitaltwinsinstances-${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 = 'dtdtiwaf' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-diagnosticDependencies' + params: { + storageAccountName: 'dep${namePrefix}diasa${serviceShort}03' + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-${uniqueString(serviceShort)}-evh-01' + eventHubNamespaceName: 'dep-${uniqueString(serviceShort)}-evh-01' + 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: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + diagnosticSettings: [ + { + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + dependsOn: [ + diagnosticDependencies + ] +}] diff --git a/avm/res/digital-twins/digital-twins-instance/version.json b/avm/res/digital-twins/digital-twins-instance/version.json new file mode 100644 index 0000000000..7fa401bdf7 --- /dev/null +++ b/avm/res/digital-twins/digital-twins-instance/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.1", + "pathFilters": [ + "./main.json" + ] +} From 0c13479de1ee82f40a746a31813e3f4325a0816e Mon Sep 17 00:00:00 2001 From: Kris Baranek Date: Fri, 22 Mar 2024 22:57:33 +0100 Subject: [PATCH 55/73] feat: New Module `avm/res/relay/namespace` (#1319) ## Description New Module `avm/res/relay/namespace`, migrated from CARML. ## Adding a new module - [x] A proposal has been submitted and approved. - [ ] I have included "Closes #{module_proposal_issue_number}" in the PR description. - [ ] I have run `brm validate` locally to verify the module files. - [x] I have run deployment tests locally to ensure the module is deployable. ## Pipeline references | Pipeline | | - | | [![avm.res.relay.namespace](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.relay.namespace.yml/badge.svg?branch=users%2Fkrbar%2FrelayModule)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.relay.namespace.yml) | --------- Co-authored-by: Alexander Sehr --- .github/CODEOWNERS | 2 +- .github/ISSUE_TEMPLATE/avm_module_issue.yml | 2 +- .github/workflows/avm.res.relay.namespace.yml | 86 + avm/res/relay/namespace/ORPHANED.md | 4 + avm/res/relay/namespace/README.md | 1366 ++++++++++ .../namespace/authorization-rule/README.md | 84 + .../namespace/authorization-rule/main.bicep | 40 + .../namespace/authorization-rule/main.json | 75 + .../namespace/hybrid-connection/README.md | 247 ++ .../authorization-rule/README.md | 92 + .../authorization-rule/main.bicep | 45 + .../authorization-rule/main.json | 79 + .../namespace/hybrid-connection/main.bicep | 152 ++ .../namespace/hybrid-connection/main.json | 381 +++ avm/res/relay/namespace/main.bicep | 431 +++ avm/res/relay/namespace/main.json | 2396 +++++++++++++++++ .../namespace/network-rule-set/README.md | 94 + .../namespace/network-rule-set/main.bicep | 48 + .../namespace/network-rule-set/main.json | 98 + .../tests/e2e/defaults/main.test.bicep | 46 + .../tests/e2e/max/dependencies.bicep | 60 + .../namespace/tests/e2e/max/main.test.bicep | 196 ++ .../tests/e2e/waf-aligned/dependencies.bicep | 49 + .../tests/e2e/waf-aligned/main.test.bicep | 148 + avm/res/relay/namespace/version.json | 7 + avm/res/relay/namespace/wcf-relay/README.md | 271 ++ .../wcf-relay/authorization-rule/README.md | 92 + .../wcf-relay/authorization-rule/main.bicep | 45 + .../wcf-relay/authorization-rule/main.json | 79 + .../wcf-relay/authorization-rule/version.json | 7 + avm/res/relay/namespace/wcf-relay/main.bicep | 180 ++ avm/res/relay/namespace/wcf-relay/main.json | 401 +++ 32 files changed, 7301 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/avm.res.relay.namespace.yml create mode 100644 avm/res/relay/namespace/ORPHANED.md create mode 100644 avm/res/relay/namespace/README.md create mode 100644 avm/res/relay/namespace/authorization-rule/README.md create mode 100644 avm/res/relay/namespace/authorization-rule/main.bicep create mode 100644 avm/res/relay/namespace/authorization-rule/main.json create mode 100644 avm/res/relay/namespace/hybrid-connection/README.md create mode 100644 avm/res/relay/namespace/hybrid-connection/authorization-rule/README.md create mode 100644 avm/res/relay/namespace/hybrid-connection/authorization-rule/main.bicep create mode 100644 avm/res/relay/namespace/hybrid-connection/authorization-rule/main.json create mode 100644 avm/res/relay/namespace/hybrid-connection/main.bicep create mode 100644 avm/res/relay/namespace/hybrid-connection/main.json create mode 100644 avm/res/relay/namespace/main.bicep create mode 100644 avm/res/relay/namespace/main.json create mode 100644 avm/res/relay/namespace/network-rule-set/README.md create mode 100644 avm/res/relay/namespace/network-rule-set/main.bicep create mode 100644 avm/res/relay/namespace/network-rule-set/main.json create mode 100644 avm/res/relay/namespace/tests/e2e/defaults/main.test.bicep create mode 100644 avm/res/relay/namespace/tests/e2e/max/dependencies.bicep create mode 100644 avm/res/relay/namespace/tests/e2e/max/main.test.bicep create mode 100644 avm/res/relay/namespace/tests/e2e/waf-aligned/dependencies.bicep create mode 100644 avm/res/relay/namespace/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/res/relay/namespace/version.json create mode 100644 avm/res/relay/namespace/wcf-relay/README.md create mode 100644 avm/res/relay/namespace/wcf-relay/authorization-rule/README.md create mode 100644 avm/res/relay/namespace/wcf-relay/authorization-rule/main.bicep create mode 100644 avm/res/relay/namespace/wcf-relay/authorization-rule/main.json create mode 100644 avm/res/relay/namespace/wcf-relay/authorization-rule/version.json create mode 100644 avm/res/relay/namespace/wcf-relay/main.bicep create mode 100644 avm/res/relay/namespace/wcf-relay/main.json diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c940e9a12e..6e1cdc9eb4 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -119,7 +119,7 @@ /avm/res/power-bi-dedicated/capacity/ @Azure/avm-res-powerbidedicated-capacity-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/purview/account/ @Azure/avm-res-purview-account-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/recovery-services/vault/ @Azure/avm-res-recoveryservices-vault-module-owners-bicep @Azure/avm-core-team-technical-bicep -#/avm/res/relay/namespace/ @Azure/avm-res-relay-namespace-module-owners-bicep @Azure/avm-core-team-technical-bicep +/avm/res/relay/namespace/ @Azure/avm-res-relay-namespace-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/resource-graph/query/ @Azure/avm-res-resourcegraph-query-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/resources/deployment-script/ @Azure/avm-res-resources-deploymentscript-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/resources/resource-group/ @Azure/avm-res-resources-resourcegroup-module-owners-bicep @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 71401f6c31..7bf85b4f2f 100644 --- a/.github/ISSUE_TEMPLATE/avm_module_issue.yml +++ b/.github/ISSUE_TEMPLATE/avm_module_issue.yml @@ -153,7 +153,7 @@ body: - "avm/res/power-bi-dedicated/capacity" - "avm/res/purview/account" - "avm/res/recovery-services/vault" - # - "avm/res/relay/namespace" + - "avm/res/relay/namespace" - "avm/res/resource-graph/query" - "avm/res/resources/deployment-script" - "avm/res/resources/resource-group" diff --git a/.github/workflows/avm.res.relay.namespace.yml b/.github/workflows/avm.res.relay.namespace.yml new file mode 100644 index 0000000000..52e8a21ebf --- /dev/null +++ b/.github/workflows/avm.res.relay.namespace.yml @@ -0,0 +1,86 @@ +name: "avm.res.relay.namespace" + +on: + schedule: + - cron: "0 12 1/15 * *" # Bi-Weekly Test (on 1st & 15th of month) + 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 + push: + branches: + - main + paths: + - ".github/actions/templates/avm-**" + - ".github/workflows/avm.template.module.yml" + - ".github/workflows/avm.res.relay.namespace.yml" + - "avm/res/relay/namespace/**" + - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/relay/namespace" + workflowPath: ".github/workflows/avm.res.relay.namespace.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-latest + name: "Initialize pipeline" + steps: + - name: "Checkout" + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: "Set input parameters to output variables" + id: get-workflow-param + uses: ./.github/actions/templates/avm-getWorkflowInput + with: + workflowPath: "${{ env.workflowPath}}" + - name: "Get module test file paths" + id: get-module-test-file-paths + uses: ./.github/actions/templates/avm-getModuleTestFiles + with: + modulePath: "${{ env.modulePath }}" + outputs: + workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }} + moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} + psRuleModuleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.psRuleModuleTestFilePaths }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Run" + permissions: + id-token: write # For OIDC + contents: write # For release tags + needs: + - job_initialize_pipeline + uses: ./.github/workflows/avm.template.module.yml + with: + workflowInput: "${{ needs.job_initialize_pipeline.outputs.workflowInput }}" + moduleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.moduleTestFilePaths }}" + psRuleModuleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.psRuleModuleTestFilePaths }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit diff --git a/avm/res/relay/namespace/ORPHANED.md b/avm/res/relay/namespace/ORPHANED.md new file mode 100644 index 0000000000..ef8fa911d2 --- /dev/null +++ b/avm/res/relay/namespace/ORPHANED.md @@ -0,0 +1,4 @@ +⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ + +- Only security and bug fixes are being handled by the AVM core team at present. +- If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! \ No newline at end of file diff --git a/avm/res/relay/namespace/README.md b/avm/res/relay/namespace/README.md new file mode 100644 index 0000000000..3a4056a67d --- /dev/null +++ b/avm/res/relay/namespace/README.md @@ -0,0 +1,1366 @@ +# Relay Namespaces `[Microsoft.Relay/namespaces]` + +> ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ +> +> - Only security and bug fixes are being handled by the AVM core team at present. +> - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! + +This module deploys a Relay Namespace + +## Navigation + +- [Resource Types](#Resource-Types) +- [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` | [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/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.Relay/namespaces` | [2021-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Relay/2021-11-01/namespaces) | +| `Microsoft.Relay/namespaces/authorizationRules` | [2021-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Relay/2021-11-01/namespaces/authorizationRules) | +| `Microsoft.Relay/namespaces/hybridConnections` | [2021-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Relay/2021-11-01/namespaces/hybridConnections) | +| `Microsoft.Relay/namespaces/hybridConnections/authorizationRules` | [2021-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Relay/2021-11-01/namespaces/hybridConnections/authorizationRules) | +| `Microsoft.Relay/namespaces/networkRuleSets` | [2021-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Relay/2021-11-01/namespaces/networkRuleSets) | +| `Microsoft.Relay/namespaces/wcfRelays` | [2021-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Relay/2021-11-01/namespaces/wcfRelays) | +| `Microsoft.Relay/namespaces/wcfRelays/authorizationRules` | [2021-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Relay/2021-11-01/namespaces/wcfRelays/authorizationRules) | + +## 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/res/relay/namespace:`. + +- [Using only defaults](#example-1-using-only-defaults) +- [Using large parameter set](#example-2-using-large-parameter-set) +- [WAF-aligned](#example-3-waf-aligned) + +### Example 1: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. + + +

+ +via Bicep module + +```bicep +module namespace 'br/public:avm/res/relay/namespace:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-rnmin' + params: { + // Required parameters + name: 'rnmin001' + // Non-required parameters + location: '' + } +} +``` + +
+

+ +

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

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

+ +via Bicep module + +```bicep +module namespace 'br/public:avm/res/relay/namespace:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-rnmax' + params: { + // Required parameters + name: 'rnmax001' + // Non-required parameters + authorizationRules: [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + { + name: 'AnotherKey' + rights: [ + 'Listen' + 'Send' + ] + } + ] + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + hybridConnections: [ + { + name: 'rnmaxhc001' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + userMetadata: '[{\'key\':\'endpoint\',\'value\':\'db-server.constoso.com:1433\'}]' + } + ] + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + networkRuleSets: { + defaultAction: 'Deny' + ipRules: [ + { + action: 'Allow' + ipMask: '10.0.1.0/32' + } + { + action: 'Allow' + ipMask: '10.0.2.0/32' + } + ] + trustedServiceAccessEnabled: true + virtualNetworkRules: [ + { + subnet: { + id: '' + ignoreMissingVnetServiceEndpoint: true + } + } + ] + } + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + '' + ] + service: 'namespace' + subnetResourceId: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + { + privateDnsZoneResourceIds: [ + '' + ] + subnetResourceId: '' + } + ] + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + skuName: 'Standard' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + wcfRelays: [ + { + name: 'rnmaxwcf001' + relayType: 'NetTcp' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + } + ] + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "rnmax001" + }, + // Non-required parameters + "authorizationRules": { + "value": [ + { + "name": "RootManageSharedAccessKey", + "rights": [ + "Listen", + "Manage", + "Send" + ] + }, + { + "name": "AnotherKey", + "rights": [ + "Listen", + "Send" + ] + } + ] + }, + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "hybridConnections": { + "value": [ + { + "name": "rnmaxhc001", + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ], + "userMetadata": "[{\"key\":\"endpoint\",\"value\":\"db-server.constoso.com:1433\"}]" + } + ] + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "networkRuleSets": { + "value": { + "defaultAction": "Deny", + "ipRules": [ + { + "action": "Allow", + "ipMask": "10.0.1.0/32" + }, + { + "action": "Allow", + "ipMask": "10.0.2.0/32" + } + ], + "trustedServiceAccessEnabled": true, + "virtualNetworkRules": [ + { + "subnet": { + "id": "", + "ignoreMissingVnetServiceEndpoint": true + } + } + ] + } + }, + "privateEndpoints": { + "value": [ + { + "privateDnsZoneResourceIds": [ + "" + ], + "service": "namespace", + "subnetResourceId": "", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + { + "privateDnsZoneResourceIds": [ + "" + ], + "subnetResourceId": "" + } + ] + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "skuName": { + "value": "Standard" + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + "wcfRelays": { + "value": [ + { + "name": "rnmaxwcf001", + "relayType": "NetTcp", + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ] + } + ] + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module namespace 'br/public:avm/res/relay/namespace:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-rnwaf' + params: { + // Required parameters + name: 'rnwaf001' + // Non-required parameters + authorizationRules: [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + { + name: 'AnotherKey' + rights: [ + 'Listen' + 'Send' + ] + } + ] + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + hybridConnections: [ + { + name: 'rnwafhc001' + userMetadata: '[{\'key\':\'endpoint\',\'value\':\'db-server.constoso.com:1433\'}]' + } + ] + location: '' + networkRuleSets: { + defaultAction: 'Deny' + ipRules: [ + { + action: 'Allow' + ipMask: '10.0.1.0/32' + } + { + action: 'Allow' + ipMask: '10.0.2.0/32' + } + ] + trustedServiceAccessEnabled: true + virtualNetworkRules: [ + { + subnet: { + id: '' + ignoreMissingVnetServiceEndpoint: true + } + } + ] + } + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + '' + ] + service: 'namespace' + subnetResourceId: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + ] + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + wcfRelays: [ + { + name: 'rnwafwcf001' + relayType: 'NetTcp' + } + ] + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "rnwaf001" + }, + // Non-required parameters + "authorizationRules": { + "value": [ + { + "name": "RootManageSharedAccessKey", + "rights": [ + "Listen", + "Manage", + "Send" + ] + }, + { + "name": "AnotherKey", + "rights": [ + "Listen", + "Send" + ] + } + ] + }, + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "hybridConnections": { + "value": [ + { + "name": "rnwafhc001", + "userMetadata": "[{\"key\":\"endpoint\",\"value\":\"db-server.constoso.com:1433\"}]" + } + ] + }, + "location": { + "value": "" + }, + "networkRuleSets": { + "value": { + "defaultAction": "Deny", + "ipRules": [ + { + "action": "Allow", + "ipMask": "10.0.1.0/32" + }, + { + "action": "Allow", + "ipMask": "10.0.2.0/32" + } + ], + "trustedServiceAccessEnabled": true, + "virtualNetworkRules": [ + { + "subnet": { + "id": "", + "ignoreMissingVnetServiceEndpoint": true + } + } + ] + } + }, + "privateEndpoints": { + "value": [ + { + "privateDnsZoneResourceIds": [ + "" + ], + "service": "namespace", + "subnetResourceId": "", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + "wcfRelays": { + "value": [ + { + "name": "rnwafwcf001", + "relayType": "NetTcp" + } + ] + } + } +} +``` + +
+

+ + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the Relay Namespace. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`authorizationRules`](#parameter-authorizationrules) | array | Authorization Rules for the Relay namespace. | +| [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`hybridConnections`](#parameter-hybridconnections) | array | The hybrid connections to create in the relay namespace. | +| [`location`](#parameter-location) | string | Location for all resources. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`networkRuleSets`](#parameter-networkrulesets) | object | 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. | +| [`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 assignments to create. | +| [`skuName`](#parameter-skuname) | string | Name of this SKU. | +| [`tags`](#parameter-tags) | object | Tags of the resource. | +| [`wcfRelays`](#parameter-wcfrelays) | array | The wcf relays to create in the relay namespace. | + +### Parameter: `name` + +Name of the Relay Namespace. + +- Required: Yes +- Type: string + +### Parameter: `authorizationRules` + +Authorization Rules for the Relay namespace. + +- Required: No +- Type: array +- Default: + ```Bicep + [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + ] + ``` + +### Parameter: `diagnosticSettings` + +The diagnostic settings of the service. + +- Required: No +- Type: array + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`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 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. | +| [`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. | + +### Parameter: `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: `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: `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: `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. + +- Required: No +- Type: string + +### Parameter: `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-diagnosticsettingsmetriccategoriescategory) | 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-diagnosticsettingsmetriccategoriesenabled) | bool | Enable or disable the category explicitly. Default is `true`. | + +### Parameter: `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: `diagnosticSettings.metricCategories.enabled` + +Enable or disable the category explicitly. Default is `true`. + +- Required: No +- Type: bool + +### Parameter: `diagnosticSettings.name` + +The name of diagnostic setting. + +- Required: No +- Type: string + +### Parameter: `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: `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: `enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `hybridConnections` + +The hybrid connections to create in the relay namespace. + +- Required: No +- Type: array +- Default: `[]` + +### 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: `networkRuleSets` + +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. + +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `privateEndpoints` + +Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`subnetResourceId`](#parameter-privateendpointssubnetresourceid) | string | Resource ID of the subnet where the endpoint needs to be created. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`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. | +| [`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. | +| [`isManualConnection`](#parameter-privateendpointsismanualconnection) | bool | If Manual Private Link Connection is required. | +| [`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. | +| [`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. | + +### Parameter: `privateEndpoints.subnetResourceId` + +Resource ID of the subnet where the endpoint needs to be created. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.applicationSecurityGroupResourceIds` + +Application security groups in which the private endpoint IP configuration is included. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.customDnsConfigs` + +Custom DNS configurations. + +- Required: No +- Type: array + +**Required parameters** + +| 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. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` + +A list of private IP addresses of the private endpoint. + +- Required: Yes +- Type: array + +### Parameter: `privateEndpoints.customNetworkInterfaceName` + +The custom name of the network interface attached to the private endpoint. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool + +### Parameter: `privateEndpoints.ipConfigurations` + +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 + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-privateendpointsipconfigurationsname) | string | The name of the resource that is unique within a resource group. | +| [`properties`](#parameter-privateendpointsipconfigurationsproperties) | object | Properties of private endpoint IP configurations. | + +### Parameter: `privateEndpoints.ipConfigurations.name` + +The name of the resource that is unique within a resource group. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.ipConfigurations.properties` + +Properties of private endpoint IP configurations. + +- Required: Yes +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`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. | + +### Parameter: `privateEndpoints.ipConfigurations.properties.groupId` + +The ID of a group obtained from the remote resource that this private endpoint should connect to. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.ipConfigurations.properties.memberName` + +The member name of a group obtained from the remote resource that this private endpoint should connect to. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.ipConfigurations.properties.privateIPAddress` + +A private IP address obtained from the private endpoint's subnet. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.isManualConnection` + +If Manual Private Link Connection is required. + +- Required: No +- Type: bool + +### Parameter: `privateEndpoints.location` + +The location to deploy the private endpoint to. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.lock` + +Specify the type of lock. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`kind`](#parameter-privateendpointslockkind) | string | Specify the type of lock. | +| [`name`](#parameter-privateendpointslockname) | string | Specify the name of lock. | + +### Parameter: `privateEndpoints.lock.kind` + +Specify the type of lock. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'CanNotDelete' + 'None' + 'ReadOnly' + ] + ``` + +### Parameter: `privateEndpoints.lock.name` + +Specify the name of lock. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.manualConnectionRequestMessage` + +A message passed to the owner of the remote resource with the manual connection request. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.name` + +The name of the private endpoint. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.privateDnsZoneGroupName` + +The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.privateDnsZoneResourceIds` + +The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`principalId`](#parameter-privateendpointsroleassignmentsprincipalid) | string | The principal ID of the principal (user/group/identity) to assign the role to. | +| [`roleDefinitionIdOrName`](#parameter-privateendpointsroleassignmentsroledefinitionidorname) | 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-privateendpointsroleassignmentscondition) | 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-privateendpointsroleassignmentsconditionversion) | string | Version of the condition. | +| [`delegatedManagedIdentityResourceId`](#parameter-privateendpointsroleassignmentsdelegatedmanagedidentityresourceid) | string | The Resource Id of the delegated managed identity resource. | +| [`description`](#parameter-privateendpointsroleassignmentsdescription) | string | The description of the role assignment. | +| [`principalType`](#parameter-privateendpointsroleassignmentsprincipaltype) | string | The principal type of the assigned principal ID. | + +### Parameter: `privateEndpoints.roleAssignments.principalId` + +The principal ID of the principal (user/group/identity) to assign the role to. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.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: `privateEndpoints.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: `privateEndpoints.roleAssignments.conditionVersion` + +Version of the condition. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + '2.0' + ] + ``` + +### Parameter: `privateEndpoints.roleAssignments.delegatedManagedIdentityResourceId` + +The Resource Id of the delegated managed identity resource. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.roleAssignments.description` + +The description of the role assignment. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.roleAssignments.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `privateEndpoints.service` + +The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.tags` + +Tags to be applied on all resources/resource groups in this deployment. + +- Required: No +- Type: object + +### Parameter: `roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**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. | +| [`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.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `skuName` + +Name of this SKU. + +- Required: No +- Type: string +- Default: `'Standard'` +- Allowed: + ```Bicep + [ + 'Standard' + ] + ``` + +### Parameter: `tags` + +Tags of the resource. + +- Required: No +- Type: object + +### Parameter: `wcfRelays` + +The wcf relays to create in the relay namespace. + +- Required: No +- Type: array +- Default: `[]` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the deployed relay namespace. | +| `resourceGroupName` | string | The resource group of the deployed relay namespace. | +| `resourceId` | string | The resource ID of the deployed relay namespace. | + +## 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/network/private-endpoint:0.4.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/relay/namespace/authorization-rule/README.md b/avm/res/relay/namespace/authorization-rule/README.md new file mode 100644 index 0000000000..3316320403 --- /dev/null +++ b/avm/res/relay/namespace/authorization-rule/README.md @@ -0,0 +1,84 @@ +# Relay Namespace Authorization Rules `[Microsoft.Relay/namespaces/authorizationRules]` + +This module deploys a Relay Namespace Authorization Rule. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Relay/namespaces/authorizationRules` | [2021-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Relay/2021-11-01/namespaces/authorizationRules) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | The name of the authorization rule. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`namespaceName`](#parameter-namespacename) | string | The name of the parent Relay Namespace for the Relay Hybrid Connection. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`rights`](#parameter-rights) | array | The rights associated with the rule. | + +### Parameter: `name` + +The name of the authorization rule. + +- Required: Yes +- Type: string + +### Parameter: `namespaceName` + +The name of the parent Relay Namespace for the Relay Hybrid Connection. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `rights` + +The rights associated with the rule. + +- Required: No +- Type: array +- Default: `[]` +- Allowed: + ```Bicep + [ + 'Listen' + 'Manage' + 'Send' + ] + ``` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the authorization rule. | +| `resourceGroupName` | string | The name of the Resource Group the authorization rule was created in. | +| `resourceId` | string | The resource ID of the authorization rule. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/relay/namespace/authorization-rule/main.bicep b/avm/res/relay/namespace/authorization-rule/main.bicep new file mode 100644 index 0000000000..73fcd7e66f --- /dev/null +++ b/avm/res/relay/namespace/authorization-rule/main.bicep @@ -0,0 +1,40 @@ +metadata name = 'Relay Namespace Authorization Rules' +metadata description = 'This module deploys a Relay Namespace Authorization Rule.' +metadata owner = 'Azure/module-maintainers' + +@description('Conditional. The name of the parent Relay Namespace for the Relay Hybrid Connection. Required if the template is used in a standalone deployment.') +@minLength(6) +@maxLength(50) +param namespaceName string + +@description('Required. The name of the authorization rule.') +param name string + +@description('Optional. The rights associated with the rule.') +@allowed([ + 'Listen' + 'Manage' + 'Send' +]) +param rights array = [] + +resource namespace 'Microsoft.Relay/namespaces@2021-11-01' existing = { + name: namespaceName +} + +resource authorizationRule 'Microsoft.Relay/namespaces/authorizationRules@2021-11-01' = { + name: name + parent: namespace + properties: { + rights: rights + } +} + +@description('The name of the authorization rule.') +output name string = authorizationRule.name + +@description('The resource ID of the authorization rule.') +output resourceId string = authorizationRule.id + +@description('The name of the Resource Group the authorization rule was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/avm/res/relay/namespace/authorization-rule/main.json b/avm/res/relay/namespace/authorization-rule/main.json new file mode 100644 index 0000000000..79bf7d77b5 --- /dev/null +++ b/avm/res/relay/namespace/authorization-rule/main.json @@ -0,0 +1,75 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.26.54.24096", + "templateHash": "8277084259418137925" + }, + "name": "Relay Namespace Authorization Rules", + "description": "This module deploys a Relay Namespace Authorization Rule.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "namespaceName": { + "type": "string", + "minLength": 6, + "maxLength": 50, + "metadata": { + "description": "Conditional. The name of the parent Relay Namespace for the Relay Hybrid Connection. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the authorization rule." + } + }, + "rights": { + "type": "array", + "defaultValue": [], + "allowedValues": [ + "Listen", + "Manage", + "Send" + ], + "metadata": { + "description": "Optional. The rights associated with the rule." + } + } + }, + "resources": [ + { + "type": "Microsoft.Relay/namespaces/authorizationRules", + "apiVersion": "2021-11-01", + "name": "[format('{0}/{1}', parameters('namespaceName'), parameters('name'))]", + "properties": { + "rights": "[parameters('rights')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the authorization rule." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the authorization rule." + }, + "value": "[resourceId('Microsoft.Relay/namespaces/authorizationRules', parameters('namespaceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the authorization rule was created in." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/relay/namespace/hybrid-connection/README.md b/avm/res/relay/namespace/hybrid-connection/README.md new file mode 100644 index 0000000000..942e7d5e26 --- /dev/null +++ b/avm/res/relay/namespace/hybrid-connection/README.md @@ -0,0 +1,247 @@ +# Relay Namespace Hybrid Connections `[Microsoft.Relay/namespaces/hybridConnections]` + +This module deploys a Relay Namespace Hybrid Connection. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [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.Relay/namespaces/hybridConnections` | [2021-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Relay/2021-11-01/namespaces/hybridConnections) | +| `Microsoft.Relay/namespaces/hybridConnections/authorizationRules` | [2021-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Relay/2021-11-01/namespaces/hybridConnections/authorizationRules) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | The name of the hybrid connection. | +| [`userMetadata`](#parameter-usermetadata) | string | The user metadata is a placeholder to store user-defined string data for the hybrid connection endpoint. For example, it can be used to store descriptive data, such as a list of teams and their contact information. Also, user-defined configuration settings can be stored. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`namespaceName`](#parameter-namespacename) | string | The name of the parent Relay Namespace for the Relay Hybrid Connection. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`authorizationRules`](#parameter-authorizationrules) | array | Authorization Rules for the Relay Hybrid Connection. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`requiresClientAuthorization`](#parameter-requiresclientauthorization) | bool | A value indicating if this hybrid connection requires client authorization. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | + +### Parameter: `name` + +The name of the hybrid connection. + +- Required: Yes +- Type: string + +### Parameter: `userMetadata` + +The user metadata is a placeholder to store user-defined string data for the hybrid connection endpoint. For example, it can be used to store descriptive data, such as a list of teams and their contact information. Also, user-defined configuration settings can be stored. + +- Required: Yes +- Type: string + +### Parameter: `namespaceName` + +The name of the parent Relay Namespace for the Relay Hybrid Connection. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `authorizationRules` + +Authorization Rules for the Relay Hybrid Connection. + +- Required: No +- Type: array +- Default: + ```Bicep + [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + { + name: 'defaultListener' + rights: [ + 'Listen' + ] + } + { + name: 'defaultSender' + rights: [ + 'Send' + ] + } + ] + ``` + +### 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: `requiresClientAuthorization` + +A value indicating if this hybrid connection requires client authorization. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**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. | +| [`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.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed hybrid connection. | +| `resourceGroupName` | string | The resource group of the deployed hybrid connection. | +| `resourceId` | string | The resource ID of the deployed hybrid connection. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/relay/namespace/hybrid-connection/authorization-rule/README.md b/avm/res/relay/namespace/hybrid-connection/authorization-rule/README.md new file mode 100644 index 0000000000..aa0e23eced --- /dev/null +++ b/avm/res/relay/namespace/hybrid-connection/authorization-rule/README.md @@ -0,0 +1,92 @@ +# Hybrid Connection Authorization Rules `[Microsoft.Relay/namespaces/hybridConnections/authorizationRules]` + +This module deploys a Hybrid Connection Authorization Rule. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Relay/namespaces/hybridConnections/authorizationRules` | [2021-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Relay/2021-11-01/namespaces/hybridConnections/authorizationRules) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | The name of the authorization rule. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`hybridConnectionName`](#parameter-hybridconnectionname) | string | The name of the parent Relay Namespace Hybrid Connection. Required if the template is used in a standalone deployment. | +| [`namespaceName`](#parameter-namespacename) | string | The name of the parent Relay Namespace. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`rights`](#parameter-rights) | array | The rights associated with the rule. | + +### Parameter: `name` + +The name of the authorization rule. + +- Required: Yes +- Type: string + +### Parameter: `hybridConnectionName` + +The name of the parent Relay Namespace Hybrid Connection. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `namespaceName` + +The name of the parent Relay Namespace. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `rights` + +The rights associated with the rule. + +- Required: No +- Type: array +- Default: `[]` +- Allowed: + ```Bicep + [ + 'Listen' + 'Manage' + 'Send' + ] + ``` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the authorization rule. | +| `resourceGroupName` | string | The name of the Resource Group the authorization rule was created in. | +| `resourceId` | string | The Resource ID of the authorization rule. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/relay/namespace/hybrid-connection/authorization-rule/main.bicep b/avm/res/relay/namespace/hybrid-connection/authorization-rule/main.bicep new file mode 100644 index 0000000000..eb204b5644 --- /dev/null +++ b/avm/res/relay/namespace/hybrid-connection/authorization-rule/main.bicep @@ -0,0 +1,45 @@ +metadata name = 'Hybrid Connection Authorization Rules' +metadata description = 'This module deploys a Hybrid Connection Authorization Rule.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. The name of the authorization rule.') +param name string + +@description('Conditional. The name of the parent Relay Namespace. Required if the template is used in a standalone deployment.') +param namespaceName string + +@description('Conditional. The name of the parent Relay Namespace Hybrid Connection. Required if the template is used in a standalone deployment.') +param hybridConnectionName string + +@description('Optional. The rights associated with the rule.') +@allowed([ + 'Listen' + 'Manage' + 'Send' +]) +param rights array = [] + +resource namespace 'Microsoft.Relay/namespaces@2021-11-01' existing = { + name: namespaceName + + resource hybridConnection 'hybridConnections@2021-11-01' existing = { + name: hybridConnectionName + } +} + +resource authorizationRule 'Microsoft.Relay/namespaces/hybridConnections/authorizationRules@2021-11-01' = { + name: name + parent: namespace::hybridConnection + properties: { + rights: rights + } +} + +@description('The name of the authorization rule.') +output name string = authorizationRule.name + +@description('The Resource ID of the authorization rule.') +output resourceId string = authorizationRule.id + +@description('The name of the Resource Group the authorization rule was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/avm/res/relay/namespace/hybrid-connection/authorization-rule/main.json b/avm/res/relay/namespace/hybrid-connection/authorization-rule/main.json new file mode 100644 index 0000000000..943c6224d2 --- /dev/null +++ b/avm/res/relay/namespace/hybrid-connection/authorization-rule/main.json @@ -0,0 +1,79 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.26.54.24096", + "templateHash": "5255934595416171239" + }, + "name": "Hybrid Connection Authorization Rules", + "description": "This module deploys a Hybrid Connection Authorization Rule.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the authorization rule." + } + }, + "namespaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Relay Namespace. Required if the template is used in a standalone deployment." + } + }, + "hybridConnectionName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Relay Namespace Hybrid Connection. Required if the template is used in a standalone deployment." + } + }, + "rights": { + "type": "array", + "defaultValue": [], + "allowedValues": [ + "Listen", + "Manage", + "Send" + ], + "metadata": { + "description": "Optional. The rights associated with the rule." + } + } + }, + "resources": [ + { + "type": "Microsoft.Relay/namespaces/hybridConnections/authorizationRules", + "apiVersion": "2021-11-01", + "name": "[format('{0}/{1}/{2}', parameters('namespaceName'), parameters('hybridConnectionName'), parameters('name'))]", + "properties": { + "rights": "[parameters('rights')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the authorization rule." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The Resource ID of the authorization rule." + }, + "value": "[resourceId('Microsoft.Relay/namespaces/hybridConnections/authorizationRules', parameters('namespaceName'), parameters('hybridConnectionName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the authorization rule was created in." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/relay/namespace/hybrid-connection/main.bicep b/avm/res/relay/namespace/hybrid-connection/main.bicep new file mode 100644 index 0000000000..74f4adec7e --- /dev/null +++ b/avm/res/relay/namespace/hybrid-connection/main.bicep @@ -0,0 +1,152 @@ +metadata name = 'Relay Namespace Hybrid Connections' +metadata description = 'This module deploys a Relay Namespace Hybrid Connection.' +metadata owner = 'Azure/module-maintainers' + +@description('Conditional. The name of the parent Relay Namespace for the Relay Hybrid Connection. Required if the template is used in a standalone deployment.') +@minLength(6) +@maxLength(50) +param namespaceName string + +@description('Required. The name of the hybrid connection.') +@minLength(6) +@maxLength(50) +param name string + +@description('Required. The user metadata is a placeholder to store user-defined string data for the hybrid connection endpoint. For example, it can be used to store descriptive data, such as a list of teams and their contact information. Also, user-defined configuration settings can be stored.') +param userMetadata string + +@description('Optional. A value indicating if this hybrid connection requires client authorization.') +param requiresClientAuthorization bool = true + +@description('Optional. Authorization Rules for the Relay Hybrid Connection.') +param authorizationRules array = [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + { + name: 'defaultListener' + rights: [ + 'Listen' + ] + } + { + name: 'defaultSender' + rights: [ + 'Send' + ] + } +] + +@description('Optional. The lock settings of the service.') +param lock lockType + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +var builtInRoleNames = { + 'Azure Relay Listener': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '26e0b698-aa6d-4085-9386-aadae190014d') + 'Azure Relay Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2787bf04-f1f5-4bfe-8383-c8a24483ee38') + 'Azure Relay Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '26baccc8-eea7-41f1-98f4-1762cc7f685d') + 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource namespace 'Microsoft.Relay/namespaces@2021-11-01' existing = { + name: namespaceName +} + +resource hybridConnection 'Microsoft.Relay/namespaces/hybridConnections@2021-11-01' = { + name: name + parent: namespace + properties: { + requiresClientAuthorization: requiresClientAuthorization + userMetadata: userMetadata + } +} + +module hybridConnection_authorizationRules 'authorization-rule/main.bicep' = [for (authorizationRule, index) in authorizationRules: { + name: '${deployment().name}-AuthorizationRule-${index}' + params: { + namespaceName: namespaceName + hybridConnectionName: hybridConnection.name + name: authorizationRule.name + rights: authorizationRule.?rights + } +} +] + +resource hybridConnection_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: hybridConnection +} + +resource hybridConnection_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(hybridConnection.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: hybridConnection +} +] + +@description('The name of the deployed hybrid connection.') +output name string = hybridConnection.name + +@description('The resource ID of the deployed hybrid connection.') +output resourceId string = hybridConnection.id + +@description('The resource group of the deployed hybrid connection.') +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('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/relay/namespace/hybrid-connection/main.json b/avm/res/relay/namespace/hybrid-connection/main.json new file mode 100644 index 0000000000..48b16cafc7 --- /dev/null +++ b/avm/res/relay/namespace/hybrid-connection/main.json @@ -0,0 +1,381 @@ +{ + "$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.26.54.24096", + "templateHash": "16736572160062029099" + }, + "name": "Relay Namespace Hybrid Connections", + "description": "This module deploys a Relay Namespace Hybrid Connection.", + "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": { + "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": { + "namespaceName": { + "type": "string", + "minLength": 6, + "maxLength": 50, + "metadata": { + "description": "Conditional. The name of the parent Relay Namespace for the Relay Hybrid Connection. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "minLength": 6, + "maxLength": 50, + "metadata": { + "description": "Required. The name of the hybrid connection." + } + }, + "userMetadata": { + "type": "string", + "metadata": { + "description": "Required. The user metadata is a placeholder to store user-defined string data for the hybrid connection endpoint. For example, it can be used to store descriptive data, such as a list of teams and their contact information. Also, user-defined configuration settings can be stored." + } + }, + "requiresClientAuthorization": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. A value indicating if this hybrid connection requires client authorization." + } + }, + "authorizationRules": { + "type": "array", + "defaultValue": [ + { + "name": "RootManageSharedAccessKey", + "rights": [ + "Listen", + "Manage", + "Send" + ] + }, + { + "name": "defaultListener", + "rights": [ + "Listen" + ] + }, + { + "name": "defaultSender", + "rights": [ + "Send" + ] + } + ], + "metadata": { + "description": "Optional. Authorization Rules for the Relay Hybrid Connection." + } + }, + "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": { + "builtInRoleNames": { + "Azure Relay Listener": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '26e0b698-aa6d-4085-9386-aadae190014d')]", + "Azure Relay Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2787bf04-f1f5-4bfe-8383-c8a24483ee38')]", + "Azure Relay Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '26baccc8-eea7-41f1-98f4-1762cc7f685d')]", + "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 (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "namespace": { + "existing": true, + "type": "Microsoft.Relay/namespaces", + "apiVersion": "2021-11-01", + "name": "[parameters('namespaceName')]" + }, + "hybridConnection": { + "type": "Microsoft.Relay/namespaces/hybridConnections", + "apiVersion": "2021-11-01", + "name": "[format('{0}/{1}', parameters('namespaceName'), parameters('name'))]", + "properties": { + "requiresClientAuthorization": "[parameters('requiresClientAuthorization')]", + "userMetadata": "[parameters('userMetadata')]" + }, + "dependsOn": [ + "namespace" + ] + }, + "hybridConnection_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.Relay/namespaces/{0}/hybridConnections/{1}', parameters('namespaceName'), 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": [ + "hybridConnection" + ] + }, + "hybridConnection_roleAssignments": { + "copy": { + "name": "hybridConnection_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Relay/namespaces/{0}/hybridConnections/{1}', parameters('namespaceName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Relay/namespaces/hybridConnections', parameters('namespaceName'), 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": [ + "hybridConnection" + ] + }, + "hybridConnection_authorizationRules": { + "copy": { + "name": "hybridConnection_authorizationRules", + "count": "[length(parameters('authorizationRules'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-AuthorizationRule-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "namespaceName": { + "value": "[parameters('namespaceName')]" + }, + "hybridConnectionName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('authorizationRules')[copyIndex()].name]" + }, + "rights": { + "value": "[tryGet(parameters('authorizationRules')[copyIndex()], 'rights')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.26.54.24096", + "templateHash": "5255934595416171239" + }, + "name": "Hybrid Connection Authorization Rules", + "description": "This module deploys a Hybrid Connection Authorization Rule.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the authorization rule." + } + }, + "namespaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Relay Namespace. Required if the template is used in a standalone deployment." + } + }, + "hybridConnectionName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Relay Namespace Hybrid Connection. Required if the template is used in a standalone deployment." + } + }, + "rights": { + "type": "array", + "defaultValue": [], + "allowedValues": [ + "Listen", + "Manage", + "Send" + ], + "metadata": { + "description": "Optional. The rights associated with the rule." + } + } + }, + "resources": [ + { + "type": "Microsoft.Relay/namespaces/hybridConnections/authorizationRules", + "apiVersion": "2021-11-01", + "name": "[format('{0}/{1}/{2}', parameters('namespaceName'), parameters('hybridConnectionName'), parameters('name'))]", + "properties": { + "rights": "[parameters('rights')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the authorization rule." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The Resource ID of the authorization rule." + }, + "value": "[resourceId('Microsoft.Relay/namespaces/hybridConnections/authorizationRules', parameters('namespaceName'), parameters('hybridConnectionName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the authorization rule was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "hybridConnection" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed hybrid connection." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed hybrid connection." + }, + "value": "[resourceId('Microsoft.Relay/namespaces/hybridConnections', parameters('namespaceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed hybrid connection." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/relay/namespace/main.bicep b/avm/res/relay/namespace/main.bicep new file mode 100644 index 0000000000..5ec2aabfb6 --- /dev/null +++ b/avm/res/relay/namespace/main.bicep @@ -0,0 +1,431 @@ +metadata name = 'Relay Namespaces' +metadata description = 'This module deploys a Relay Namespace' +metadata owner = 'Azure/module-maintainers' + +@description('Required. Name of the Relay Namespace.') +@minLength(6) +@maxLength(50) +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Name of this SKU.') +@allowed([ + 'Standard' +]) +param skuName string = 'Standard' + +@description('Optional. Authorization Rules for the Relay namespace.') +param authorizationRules array = [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } +] + +@description('Optional. The diagnostic settings of the service.') +param diagnosticSettings diagnosticSettingType + +@description('Optional. The lock settings of the service.') +param lock lockType + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +@description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') +param privateEndpoints privateEndpointType + +@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 = {} + +@description('Optional. Tags of the resource.') +param tags object? + +@description('Optional. Enable/Disable usage telemetry for module.') +param enableTelemetry bool = true + +@description('Optional. The hybrid connections to create in the relay namespace.') +param hybridConnections array = [] + +@description('Optional. The wcf relays to create in the relay namespace.') +param wcfRelays array = [] + +var builtInRoleNames = { + 'Azure Relay Listener': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '26e0b698-aa6d-4085-9386-aadae190014d') + 'Azure Relay Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2787bf04-f1f5-4bfe-8383-c8a24483ee38') + 'Azure Relay Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '26baccc8-eea7-41f1-98f4-1762cc7f685d') + 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.relay-namespace.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } + } + } + } +} + +resource namespace 'Microsoft.Relay/namespaces@2021-11-01' = { + name: name + location: location + tags: empty(tags) ? null : tags + sku: { + name: skuName + } + properties: {} +} + +module namespace_authorizationRules 'authorization-rule/main.bicep' = [for (authorizationRule, index) in authorizationRules: { + name: '${uniqueString(deployment().name, location)}-AuthorizationRules-${index}' + params: { + namespaceName: namespace.name + name: authorizationRule.name + rights: contains(authorizationRule, 'rights') ? authorizationRule.rights : [] + } +}] + +module namespace_networkRuleSet 'network-rule-set/main.bicep' = if (!empty(networkRuleSets) || !empty(privateEndpoints)) { + name: '${uniqueString(deployment().name, location)}-NetworkRuleSet' + params: { + namespaceName: namespace.name + publicNetworkAccess: contains(networkRuleSets, 'publicNetworkAccess') ? networkRuleSets.publicNetworkAccess : (!empty(privateEndpoints) && empty(networkRuleSets) ? 'Disabled' : 'Enabled') + defaultAction: contains(networkRuleSets, 'defaultAction') ? networkRuleSets.defaultAction : 'Allow' + ipRules: contains(networkRuleSets, 'ipRules') ? networkRuleSets.ipRules : [] + } +} + +module namespace_hybridConnections 'hybrid-connection/main.bicep' = [for (hybridConnection, index) in hybridConnections: { + name: '${uniqueString(deployment().name, location)}-HybridConnection-${index}' + params: { + namespaceName: namespace.name + name: hybridConnection.name + authorizationRules: contains(hybridConnection, 'authorizationRules') ? hybridConnection.authorizationRules : [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + { + name: 'defaultListener' + rights: [ + 'Listen' + ] + } + { + name: 'defaultSender' + rights: [ + 'Send' + ] + } + ] + requiresClientAuthorization: contains(hybridConnection, 'requiresClientAuthorization') ? hybridConnection.requiresClientAuthorization : true + userMetadata: hybridConnection.userMetadata + } +}] + +module namespace_wcfRelays 'wcf-relay/main.bicep' = [for (wcfRelay, index) in wcfRelays: { + name: '${uniqueString(deployment().name, location)}-WcfRelay-${index}' + params: { + namespaceName: namespace.name + name: wcfRelay.name + authorizationRules: contains(wcfRelay, 'authorizationRules') ? wcfRelay.authorizationRules : [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + { + name: 'defaultListener' + rights: [ + 'Listen' + ] + } + { + name: 'defaultSender' + rights: [ + 'Send' + ] + } + ] + relayType: wcfRelay.relayType + requiresClientAuthorization: contains(wcfRelay, 'requiresClientAuthorization') ? wcfRelay.requiresClientAuthorization : true + requiresTransportSecurity: contains(wcfRelay, 'requiresTransportSecurity') ? wcfRelay.requiresTransportSecurity : true + userMetadata: contains(wcfRelay, 'userMetadata') ? wcfRelay.userMetadata : null + } +}] + +resource namespace_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: namespace +} + +resource namespace_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + }] + logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + }] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: namespace +}] + +module namespace_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.1' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-namespace-PrivateEndpoint-${index}' + scope: resourceGroup(privateEndpoint.?resourceGroupName ?? '') + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(namespace.id, '/'))}-${privateEndpoint.?service ?? 'namespace'}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(namespace.id, '/'))}-${privateEndpoint.?service ?? 'namespace'}-${index}' + properties: { + privateLinkServiceId: namespace.id + groupIds: [ + privateEndpoint.?service ?? 'namespace' + ] + } + } + ] : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(namespace.id, '/'))}-${privateEndpoint.?service ?? 'namespace'}-${index}' + properties: { + privateLinkServiceId: namespace.id + groupIds: [ + privateEndpoint.?service ?? 'namespace' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } + ] : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } +}] + +resource namespace_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(namespace.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: namespace +}] +@description('The resource ID of the deployed relay namespace.') +output resourceId string = namespace.id + +@description('The resource group of the deployed relay namespace.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the deployed relay namespace.') +output name string = namespace.name + +@description('The location the resource was deployed into.') +output location string = namespace.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('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 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? +}[]? + +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 new file mode 100644 index 0000000000..9ede75558f --- /dev/null +++ b/avm/res/relay/namespace/main.json @@ -0,0 +1,2396 @@ +{ + "$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.26.54.24096", + "templateHash": "10643789990116879548" + }, + "name": "Relay Namespaces", + "description": "This module deploys a Relay Namespace", + "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": { + "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." + } + }, + "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." + } + } + } + }, + "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 + } + }, + "parameters": { + "name": { + "type": "string", + "minLength": 6, + "maxLength": 50, + "metadata": { + "description": "Required. Name of the Relay Namespace." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "skuName": { + "type": "string", + "defaultValue": "Standard", + "allowedValues": [ + "Standard" + ], + "metadata": { + "description": "Optional. Name of this SKU." + } + }, + "authorizationRules": { + "type": "array", + "defaultValue": [ + { + "name": "RootManageSharedAccessKey", + "rights": [ + "Listen", + "Manage", + "Send" + ] + } + ], + "metadata": { + "description": "Optional. Authorization Rules for the Relay namespace." + } + }, + "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." + } + }, + "privateEndpoints": { + "$ref": "#/definitions/privateEndpointType", + "metadata": { + "description": "Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible." + } + }, + "networkRuleSets": { + "type": "object", + "defaultValue": {}, + "metadata": { + "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." + } + }, + "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." + } + }, + "hybridConnections": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The hybrid connections to create in the relay namespace." + } + }, + "wcfRelays": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The wcf relays to create in the relay namespace." + } + } + }, + "variables": { + "builtInRoleNames": { + "Azure Relay Listener": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '26e0b698-aa6d-4085-9386-aadae190014d')]", + "Azure Relay Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2787bf04-f1f5-4bfe-8383-c8a24483ee38')]", + "Azure Relay Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '26baccc8-eea7-41f1-98f4-1762cc7f685d')]", + "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 (Preview)": "[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": "2023-07-01", + "name": "[format('46d3xbcp.res.relay-namespace.{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" + } + } + } + } + }, + "namespace": { + "type": "Microsoft.Relay/namespaces", + "apiVersion": "2021-11-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[if(empty(parameters('tags')), null(), parameters('tags'))]", + "sku": { + "name": "[parameters('skuName')]" + }, + "properties": {} + }, + "namespace_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.Relay/namespaces/{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": [ + "namespace" + ] + }, + "namespace_diagnosticSettings": { + "copy": { + "name": "namespace_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Relay/namespaces/{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": [ + "namespace" + ] + }, + "namespace_roleAssignments": { + "copy": { + "name": "namespace_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Relay/namespaces/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Relay/namespaces', 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": [ + "namespace" + ] + }, + "namespace_authorizationRules": { + "copy": { + "name": "namespace_authorizationRules", + "count": "[length(parameters('authorizationRules'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-AuthorizationRules-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "namespaceName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('authorizationRules')[copyIndex()].name]" + }, + "rights": "[if(contains(parameters('authorizationRules')[copyIndex()], 'rights'), createObject('value', parameters('authorizationRules')[copyIndex()].rights), createObject('value', createArray()))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.26.54.24096", + "templateHash": "8277084259418137925" + }, + "name": "Relay Namespace Authorization Rules", + "description": "This module deploys a Relay Namespace Authorization Rule.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "namespaceName": { + "type": "string", + "minLength": 6, + "maxLength": 50, + "metadata": { + "description": "Conditional. The name of the parent Relay Namespace for the Relay Hybrid Connection. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the authorization rule." + } + }, + "rights": { + "type": "array", + "defaultValue": [], + "allowedValues": [ + "Listen", + "Manage", + "Send" + ], + "metadata": { + "description": "Optional. The rights associated with the rule." + } + } + }, + "resources": [ + { + "type": "Microsoft.Relay/namespaces/authorizationRules", + "apiVersion": "2021-11-01", + "name": "[format('{0}/{1}', parameters('namespaceName'), parameters('name'))]", + "properties": { + "rights": "[parameters('rights')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the authorization rule." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the authorization rule." + }, + "value": "[resourceId('Microsoft.Relay/namespaces/authorizationRules', parameters('namespaceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the authorization rule was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "namespace" + ] + }, + "namespace_networkRuleSet": { + "condition": "[or(not(empty(parameters('networkRuleSets'))), not(empty(parameters('privateEndpoints'))))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-NetworkRuleSet', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "namespaceName": { + "value": "[parameters('name')]" + }, + "publicNetworkAccess": "[if(contains(parameters('networkRuleSets'), 'publicNetworkAccess'), createObject('value', parameters('networkRuleSets').publicNetworkAccess), if(and(not(empty(parameters('privateEndpoints'))), empty(parameters('networkRuleSets'))), createObject('value', 'Disabled'), createObject('value', 'Enabled')))]", + "defaultAction": "[if(contains(parameters('networkRuleSets'), 'defaultAction'), createObject('value', parameters('networkRuleSets').defaultAction), createObject('value', 'Allow'))]", + "ipRules": "[if(contains(parameters('networkRuleSets'), 'ipRules'), createObject('value', parameters('networkRuleSets').ipRules), createObject('value', createArray()))]" + }, + "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.26.54.24096", + "templateHash": "8815382204301394365" + }, + "name": "Relay Namespace Network Rules Sets", + "description": "This module deploys a Relay Namespace Network Rule Set.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "namespaceName": { + "type": "string", + "minLength": 6, + "maxLength": 50, + "metadata": { + "description": "Conditional. The name of the parent Relay Namespace for the Relay Network Rule Set. Required if the template is used in a standalone deployment." + } + }, + "publicNetworkAccess": { + "type": "string", + "defaultValue": "Enabled", + "allowedValues": [ + "Enabled", + "Disabled" + ], + "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", + "defaultValue": "Allow", + "allowedValues": [ + "Allow", + "Deny" + ], + "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." + } + }, + "ipRules": { + "type": "array", + "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\"." + } + } + }, + "resources": { + "namespace": { + "existing": true, + "type": "Microsoft.Relay/namespaces", + "apiVersion": "2021-11-01", + "name": "[parameters('namespaceName')]" + }, + "networkRuleSet": { + "type": "Microsoft.Relay/namespaces/networkRuleSets", + "apiVersion": "2021-11-01", + "name": "[format('{0}/{1}', parameters('namespaceName'), 'default')]", + "properties": { + "publicNetworkAccess": "[parameters('publicNetworkAccess')]", + "defaultAction": "[if(equals(parameters('publicNetworkAccess'), 'Disabled'), null(), if(not(empty(parameters('ipRules'))), 'Deny', parameters('defaultAction')))]", + "ipRules": "[if(equals(parameters('publicNetworkAccess'), 'Disabled'), null(), parameters('ipRules'))]" + }, + "dependsOn": [ + "namespace" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the network rule set." + }, + "value": "default" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the network rule set." + }, + "value": "[resourceId('Microsoft.Relay/namespaces/networkRuleSets', parameters('namespaceName'), 'default')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the network rule set was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "namespace" + ] + }, + "namespace_hybridConnections": { + "copy": { + "name": "namespace_hybridConnections", + "count": "[length(parameters('hybridConnections'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-HybridConnection-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "namespaceName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('hybridConnections')[copyIndex()].name]" + }, + "authorizationRules": "[if(contains(parameters('hybridConnections')[copyIndex()], 'authorizationRules'), createObject('value', parameters('hybridConnections')[copyIndex()].authorizationRules), createObject('value', createArray(createObject('name', 'RootManageSharedAccessKey', 'rights', createArray('Listen', 'Manage', 'Send')), createObject('name', 'defaultListener', 'rights', createArray('Listen')), createObject('name', 'defaultSender', 'rights', createArray('Send')))))]", + "requiresClientAuthorization": "[if(contains(parameters('hybridConnections')[copyIndex()], 'requiresClientAuthorization'), createObject('value', parameters('hybridConnections')[copyIndex()].requiresClientAuthorization), createObject('value', true()))]", + "userMetadata": { + "value": "[parameters('hybridConnections')[copyIndex()].userMetadata]" + } + }, + "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.26.54.24096", + "templateHash": "16736572160062029099" + }, + "name": "Relay Namespace Hybrid Connections", + "description": "This module deploys a Relay Namespace Hybrid Connection.", + "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": { + "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": { + "namespaceName": { + "type": "string", + "minLength": 6, + "maxLength": 50, + "metadata": { + "description": "Conditional. The name of the parent Relay Namespace for the Relay Hybrid Connection. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "minLength": 6, + "maxLength": 50, + "metadata": { + "description": "Required. The name of the hybrid connection." + } + }, + "userMetadata": { + "type": "string", + "metadata": { + "description": "Required. The user metadata is a placeholder to store user-defined string data for the hybrid connection endpoint. For example, it can be used to store descriptive data, such as a list of teams and their contact information. Also, user-defined configuration settings can be stored." + } + }, + "requiresClientAuthorization": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. A value indicating if this hybrid connection requires client authorization." + } + }, + "authorizationRules": { + "type": "array", + "defaultValue": [ + { + "name": "RootManageSharedAccessKey", + "rights": [ + "Listen", + "Manage", + "Send" + ] + }, + { + "name": "defaultListener", + "rights": [ + "Listen" + ] + }, + { + "name": "defaultSender", + "rights": [ + "Send" + ] + } + ], + "metadata": { + "description": "Optional. Authorization Rules for the Relay Hybrid Connection." + } + }, + "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": { + "builtInRoleNames": { + "Azure Relay Listener": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '26e0b698-aa6d-4085-9386-aadae190014d')]", + "Azure Relay Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2787bf04-f1f5-4bfe-8383-c8a24483ee38')]", + "Azure Relay Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '26baccc8-eea7-41f1-98f4-1762cc7f685d')]", + "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 (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "namespace": { + "existing": true, + "type": "Microsoft.Relay/namespaces", + "apiVersion": "2021-11-01", + "name": "[parameters('namespaceName')]" + }, + "hybridConnection": { + "type": "Microsoft.Relay/namespaces/hybridConnections", + "apiVersion": "2021-11-01", + "name": "[format('{0}/{1}', parameters('namespaceName'), parameters('name'))]", + "properties": { + "requiresClientAuthorization": "[parameters('requiresClientAuthorization')]", + "userMetadata": "[parameters('userMetadata')]" + }, + "dependsOn": [ + "namespace" + ] + }, + "hybridConnection_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.Relay/namespaces/{0}/hybridConnections/{1}', parameters('namespaceName'), 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": [ + "hybridConnection" + ] + }, + "hybridConnection_roleAssignments": { + "copy": { + "name": "hybridConnection_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Relay/namespaces/{0}/hybridConnections/{1}', parameters('namespaceName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Relay/namespaces/hybridConnections', parameters('namespaceName'), 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": [ + "hybridConnection" + ] + }, + "hybridConnection_authorizationRules": { + "copy": { + "name": "hybridConnection_authorizationRules", + "count": "[length(parameters('authorizationRules'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-AuthorizationRule-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "namespaceName": { + "value": "[parameters('namespaceName')]" + }, + "hybridConnectionName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('authorizationRules')[copyIndex()].name]" + }, + "rights": { + "value": "[tryGet(parameters('authorizationRules')[copyIndex()], 'rights')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.26.54.24096", + "templateHash": "5255934595416171239" + }, + "name": "Hybrid Connection Authorization Rules", + "description": "This module deploys a Hybrid Connection Authorization Rule.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the authorization rule." + } + }, + "namespaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Relay Namespace. Required if the template is used in a standalone deployment." + } + }, + "hybridConnectionName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Relay Namespace Hybrid Connection. Required if the template is used in a standalone deployment." + } + }, + "rights": { + "type": "array", + "defaultValue": [], + "allowedValues": [ + "Listen", + "Manage", + "Send" + ], + "metadata": { + "description": "Optional. The rights associated with the rule." + } + } + }, + "resources": [ + { + "type": "Microsoft.Relay/namespaces/hybridConnections/authorizationRules", + "apiVersion": "2021-11-01", + "name": "[format('{0}/{1}/{2}', parameters('namespaceName'), parameters('hybridConnectionName'), parameters('name'))]", + "properties": { + "rights": "[parameters('rights')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the authorization rule." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The Resource ID of the authorization rule." + }, + "value": "[resourceId('Microsoft.Relay/namespaces/hybridConnections/authorizationRules', parameters('namespaceName'), parameters('hybridConnectionName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the authorization rule was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "hybridConnection" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed hybrid connection." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed hybrid connection." + }, + "value": "[resourceId('Microsoft.Relay/namespaces/hybridConnections', parameters('namespaceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed hybrid connection." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "namespace" + ] + }, + "namespace_wcfRelays": { + "copy": { + "name": "namespace_wcfRelays", + "count": "[length(parameters('wcfRelays'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-WcfRelay-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "namespaceName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('wcfRelays')[copyIndex()].name]" + }, + "authorizationRules": "[if(contains(parameters('wcfRelays')[copyIndex()], 'authorizationRules'), createObject('value', parameters('wcfRelays')[copyIndex()].authorizationRules), createObject('value', createArray(createObject('name', 'RootManageSharedAccessKey', 'rights', createArray('Listen', 'Manage', 'Send')), createObject('name', 'defaultListener', 'rights', createArray('Listen')), createObject('name', 'defaultSender', 'rights', createArray('Send')))))]", + "relayType": { + "value": "[parameters('wcfRelays')[copyIndex()].relayType]" + }, + "requiresClientAuthorization": "[if(contains(parameters('wcfRelays')[copyIndex()], 'requiresClientAuthorization'), createObject('value', parameters('wcfRelays')[copyIndex()].requiresClientAuthorization), createObject('value', true()))]", + "requiresTransportSecurity": "[if(contains(parameters('wcfRelays')[copyIndex()], 'requiresTransportSecurity'), createObject('value', parameters('wcfRelays')[copyIndex()].requiresTransportSecurity), createObject('value', true()))]", + "userMetadata": "[if(contains(parameters('wcfRelays')[copyIndex()], 'userMetadata'), createObject('value', parameters('wcfRelays')[copyIndex()].userMetadata), createObject('value', null()))]" + }, + "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.26.54.24096", + "templateHash": "9397973991776922121" + }, + "name": "Relay Namespace WCF Relays", + "description": "This module deploys a Relay Namespace WCF Relay.", + "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": { + "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": { + "namespaceName": { + "type": "string", + "minLength": 6, + "maxLength": 50, + "metadata": { + "description": "Conditional. The name of the parent Relay Namespace for the WCF Relay. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "minLength": 6, + "maxLength": 50, + "metadata": { + "description": "Required. Name of the WCF Relay." + } + }, + "relayType": { + "type": "string", + "allowedValues": [ + "Http", + "NetTcp" + ], + "metadata": { + "description": "Required. Type of WCF Relay." + } + }, + "requiresClientAuthorization": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. A value indicating if this relay requires client authorization." + } + }, + "requiresTransportSecurity": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. A value indicating if this relay requires transport security." + } + }, + "userMetadata": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. User-defined string data for the WCF Relay." + } + }, + "authorizationRules": { + "type": "array", + "defaultValue": [ + { + "name": "RootManageSharedAccessKey", + "rights": [ + "Listen", + "Manage", + "Send" + ] + }, + { + "name": "defaultListener", + "rights": [ + "Listen" + ] + }, + { + "name": "defaultSender", + "rights": [ + "Send" + ] + } + ], + "metadata": { + "description": "Optional. Authorization Rules for the WCF Relay." + } + }, + "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": { + "builtInRoleNames": { + "Azure Relay Listener": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '26e0b698-aa6d-4085-9386-aadae190014d')]", + "Azure Relay Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2787bf04-f1f5-4bfe-8383-c8a24483ee38')]", + "Azure Relay Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '26baccc8-eea7-41f1-98f4-1762cc7f685d')]", + "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 (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "namespace": { + "existing": true, + "type": "Microsoft.Relay/namespaces", + "apiVersion": "2021-11-01", + "name": "[parameters('namespaceName')]" + }, + "wcfRelay": { + "type": "Microsoft.Relay/namespaces/wcfRelays", + "apiVersion": "2021-11-01", + "name": "[format('{0}/{1}', parameters('namespaceName'), parameters('name'))]", + "properties": { + "relayType": "[parameters('relayType')]", + "requiresClientAuthorization": "[parameters('requiresClientAuthorization')]", + "requiresTransportSecurity": "[parameters('requiresTransportSecurity')]", + "userMetadata": "[parameters('userMetadata')]" + }, + "dependsOn": [ + "namespace" + ] + }, + "wcfRelay_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.Relay/namespaces/{0}/wcfRelays/{1}', parameters('namespaceName'), 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": [ + "wcfRelay" + ] + }, + "wcfRelay_roleAssignments": { + "copy": { + "name": "wcfRelay_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Relay/namespaces/{0}/wcfRelays/{1}', parameters('namespaceName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Relay/namespaces/wcfRelays', parameters('namespaceName'), 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": [ + "wcfRelay" + ] + }, + "wcfRelay_authorizationRules": { + "copy": { + "name": "wcfRelay_authorizationRules", + "count": "[length(parameters('authorizationRules'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-AuthorizationRule-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "namespaceName": { + "value": "[parameters('namespaceName')]" + }, + "wcfRelayName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('authorizationRules')[copyIndex()].name]" + }, + "rights": { + "value": "[tryGet(parameters('authorizationRules')[copyIndex()], 'rights')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.26.54.24096", + "templateHash": "8736725131114489503" + }, + "name": "WCF Relay Authorization Rules", + "description": "This module deploys a WCF Relay Authorization Rule.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the authorization rule." + } + }, + "namespaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Relay Namespace. Required if the template is used in a standalone deployment." + } + }, + "wcfRelayName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Relay Namespace WCF Relay. Required if the template is used in a standalone deployment." + } + }, + "rights": { + "type": "array", + "defaultValue": [], + "allowedValues": [ + "Listen", + "Manage", + "Send" + ], + "metadata": { + "description": "Optional. The rights associated with the rule." + } + } + }, + "resources": [ + { + "type": "Microsoft.Relay/namespaces/wcfRelays/authorizationRules", + "apiVersion": "2021-11-01", + "name": "[format('{0}/{1}/{2}', parameters('namespaceName'), parameters('wcfRelayName'), parameters('name'))]", + "properties": { + "rights": "[parameters('rights')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the authorization rule." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The Resource ID of the authorization rule." + }, + "value": "[resourceId('Microsoft.Relay/namespaces/wcfRelays/authorizationRules', parameters('namespaceName'), parameters('wcfRelayName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the authorization rule was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "wcfRelay" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed wcf relay." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed wcf relay." + }, + "value": "[resourceId('Microsoft.Relay/namespaces/wcfRelays', parameters('namespaceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed wcf relay." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "namespace" + ] + }, + "namespace_privateEndpoints": { + "copy": { + "name": "namespace_privateEndpoints", + "count": "[length(coalesce(parameters('privateEndpoints'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-namespace-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.Relay/namespaces', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'namespace'), copyIndex()))]" + }, + "privateLinkServiceConnections": "[if(not(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections'), true())), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.Relay/namespaces', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'namespace'), copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.Relay/namespaces', parameters('name')), 'groupIds', createArray(coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'namespace')))))), createObject('value', null()))]", + "manualPrivateLinkServiceConnections": "[if(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections'), true()), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.Relay/namespaces', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'namespace'), copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.Relay/namespaces', parameters('name')), 'groupIds', createArray(coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'namespace')), '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'))]" + }, + "privateDnsZoneGroupName": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneGroupName')]" + }, + "privateDnsZoneResourceIds": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneResourceIds')]" + }, + "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.25.53.49325", + "templateHash": "4120048060064073955" + }, + "name": "Private Endpoints", + "description": "This module deploys a Private Endpoint.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "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." + } + }, + "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 + }, + "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", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "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", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "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 + } + }, + "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." + } + }, + "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", + "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." + } + }, + "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": { + "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": "2023-07-01", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.4.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-04-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(parameters('roleAssignments'), 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)]", + "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": [ + "privateEndpoint" + ] + }, + "privateEndpoint_privateDnsZoneGroup": { + "condition": "[not(empty(parameters('privateDnsZoneResourceIds')))]", + "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": "[coalesce(parameters('privateDnsZoneGroupName'), 'default')]" + }, + "privateDNSResourceIds": { + "value": "[coalesce(parameters('privateDnsZoneResourceIds'), createArray())]" + }, + "privateEndpointName": { + "value": "[parameters('name')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.25.53.49325", + "templateHash": "11244630631275470040" + }, + "name": "Private Endpoint Private DNS Zone Groups", + "description": "This module deploys a Private Endpoint Private DNS Zone Group.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "privateEndpointName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent private endpoint. Required if the template is used in a standalone deployment." + } + }, + "privateDNSResourceIds": { + "type": "array", + "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." + } + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the private DNS zone group." + } + } + }, + "variables": { + "copy": [ + { + "name": "privateDnsZoneConfigs", + "count": "[length(parameters('privateDNSResourceIds'))]", + "input": { + "name": "[last(split(parameters('privateDNSResourceIds')[copyIndex('privateDnsZoneConfigs')], '/'))]", + "properties": { + "privateDnsZoneId": "[parameters('privateDNSResourceIds')[copyIndex('privateDnsZoneConfigs')]]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2023-04-01", + "name": "[format('{0}/{1}', parameters('privateEndpointName'), parameters('name'))]", + "properties": { + "privateDnsZoneConfigs": "[variables('privateDnsZoneConfigs')]" + } + } + ], + "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-04-01', 'full').location]" + }, + "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])]" + } + } + } + }, + "dependsOn": [ + "namespace" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed relay namespace." + }, + "value": "[resourceId('Microsoft.Relay/namespaces', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed relay namespace." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed relay namespace." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('namespace', '2021-11-01', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/relay/namespace/network-rule-set/README.md b/avm/res/relay/namespace/network-rule-set/README.md new file mode 100644 index 0000000000..6d8e41f771 --- /dev/null +++ b/avm/res/relay/namespace/network-rule-set/README.md @@ -0,0 +1,94 @@ +# Relay Namespace Network Rules Sets `[Microsoft.Relay/namespaces/networkRuleSets]` + +This module deploys a Relay Namespace Network Rule Set. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Relay/namespaces/networkRuleSets` | [2021-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Relay/2021-11-01/namespaces/networkRuleSets) | + +## Parameters + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`namespaceName`](#parameter-namespacename) | string | The name of the parent Relay Namespace for the Relay Network Rule Set. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`defaultAction`](#parameter-defaultaction) | string | 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. | +| [`ipRules`](#parameter-iprules) | array | List of IpRules. It will not be set if publicNetworkAccess is "Disabled". Otherwise, when used, defaultAction will be set to "Deny". | +| [`publicNetworkAccess`](#parameter-publicnetworkaccess) | string | 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. | + +### Parameter: `namespaceName` + +The name of the parent Relay Namespace for the Relay Network Rule Set. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `defaultAction` + +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. + +- Required: No +- Type: string +- Default: `'Allow'` +- Allowed: + ```Bicep + [ + 'Allow' + 'Deny' + ] + ``` + +### Parameter: `ipRules` + +List of IpRules. It will not be set if publicNetworkAccess is "Disabled". Otherwise, when used, defaultAction will be set to "Deny". + +- Required: No +- Type: array + +### Parameter: `publicNetworkAccess` + +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. + +- Required: No +- Type: string +- Default: `'Enabled'` +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the network rule set. | +| `resourceGroupName` | string | The name of the resource group the network rule set was created in. | +| `resourceId` | string | The resource ID of the network rule set. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/relay/namespace/network-rule-set/main.bicep b/avm/res/relay/namespace/network-rule-set/main.bicep new file mode 100644 index 0000000000..567fdfb106 --- /dev/null +++ b/avm/res/relay/namespace/network-rule-set/main.bicep @@ -0,0 +1,48 @@ +metadata name = 'Relay Namespace Network Rules Sets' +metadata description = 'This module deploys a Relay Namespace Network Rule Set.' +metadata owner = 'Azure/module-maintainers' + +@description('Conditional. The name of the parent Relay Namespace for the Relay Network Rule Set. Required if the template is used in a standalone deployment.') +@minLength(6) +@maxLength(50) +param namespaceName string + +@allowed([ + 'Enabled' + 'Disabled' +]) +@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.') +param publicNetworkAccess string = 'Enabled' + +@allowed([ + 'Allow' + 'Deny' +]) +@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.') +param defaultAction string = 'Allow' + +@description('Optional. List of IpRules. It will not be set if publicNetworkAccess is "Disabled". Otherwise, when used, defaultAction will be set to "Deny".') +param ipRules array? + +resource namespace 'Microsoft.Relay/namespaces@2021-11-01' existing = { + name: namespaceName +} + +resource networkRuleSet 'Microsoft.Relay/namespaces/networkRuleSets@2021-11-01' = { + name: 'default' + parent: namespace + properties: { + publicNetworkAccess: publicNetworkAccess + defaultAction: publicNetworkAccess == 'Disabled' ? null : (!empty(ipRules) ? 'Deny' : defaultAction) + ipRules: publicNetworkAccess == 'Disabled' ? null : ipRules + } +} + +@description('The name of the network rule set.') +output name string = networkRuleSet.name + +@description('The resource ID of the network rule set.') +output resourceId string = networkRuleSet.id + +@description('The name of the resource group the network rule set was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/avm/res/relay/namespace/network-rule-set/main.json b/avm/res/relay/namespace/network-rule-set/main.json new file mode 100644 index 0000000000..57d202ae74 --- /dev/null +++ b/avm/res/relay/namespace/network-rule-set/main.json @@ -0,0 +1,98 @@ +{ + "$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.26.54.24096", + "templateHash": "8815382204301394365" + }, + "name": "Relay Namespace Network Rules Sets", + "description": "This module deploys a Relay Namespace Network Rule Set.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "namespaceName": { + "type": "string", + "minLength": 6, + "maxLength": 50, + "metadata": { + "description": "Conditional. The name of the parent Relay Namespace for the Relay Network Rule Set. Required if the template is used in a standalone deployment." + } + }, + "publicNetworkAccess": { + "type": "string", + "defaultValue": "Enabled", + "allowedValues": [ + "Enabled", + "Disabled" + ], + "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", + "defaultValue": "Allow", + "allowedValues": [ + "Allow", + "Deny" + ], + "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." + } + }, + "ipRules": { + "type": "array", + "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\"." + } + } + }, + "resources": { + "namespace": { + "existing": true, + "type": "Microsoft.Relay/namespaces", + "apiVersion": "2021-11-01", + "name": "[parameters('namespaceName')]" + }, + "networkRuleSet": { + "type": "Microsoft.Relay/namespaces/networkRuleSets", + "apiVersion": "2021-11-01", + "name": "[format('{0}/{1}', parameters('namespaceName'), 'default')]", + "properties": { + "publicNetworkAccess": "[parameters('publicNetworkAccess')]", + "defaultAction": "[if(equals(parameters('publicNetworkAccess'), 'Disabled'), null(), if(not(empty(parameters('ipRules'))), 'Deny', parameters('defaultAction')))]", + "ipRules": "[if(equals(parameters('publicNetworkAccess'), 'Disabled'), null(), parameters('ipRules'))]" + }, + "dependsOn": [ + "namespace" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the network rule set." + }, + "value": "default" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the network rule set." + }, + "value": "[resourceId('Microsoft.Relay/namespaces/networkRuleSets', parameters('namespaceName'), 'default')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the network rule set was created in." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/relay/namespace/tests/e2e/defaults/main.test.bicep b/avm/res/relay/namespace/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..a3f2154be3 --- /dev/null +++ b/avm/res/relay/namespace/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,46 @@ +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}-relay.namespaces-${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 = 'rnmin' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +// ============== // +// 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 + } +}] diff --git a/avm/res/relay/namespace/tests/e2e/max/dependencies.bicep b/avm/res/relay/namespace/tests/e2e/max/dependencies.bicep new file mode 100644 index 0000000000..cf1b2ab392 --- /dev/null +++ b/avm/res/relay/namespace/tests/e2e/max/dependencies.bicep @@ -0,0 +1,60 @@ +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +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) + } + } + ] + } +} + +resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { + name: 'privatelink.servicebus.windows.net' + location: 'global' + + resource virtualNetworkLinks 'virtualNetworkLinks@2020-06-01' = { + name: '${virtualNetwork.name}-vnetlink' + location: 'global' + properties: { + virtualNetwork: { + id: virtualNetwork.id + } + registrationEnabled: false + } + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId + +@description('The resource ID of the created Private DNS Zone.') +output privateDNSZoneResourceId string = privateDNSZone.id diff --git a/avm/res/relay/namespace/tests/e2e/max/main.test.bicep b/avm/res/relay/namespace/tests/e2e/max/main.test.bicep new file mode 100644 index 0000000000..430b6bae17 --- /dev/null +++ b/avm/res/relay/namespace/tests/e2e/max/main.test.bicep @@ -0,0 +1,196 @@ +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}-relay.namespaces-${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 = 'rnmax' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: resourceLocation + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-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 + } +} + +// ============== // +// 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 + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + skuName: 'Standard' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + 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' + } + ] + networkRuleSets: { + defaultAction: 'Deny' + trustedServiceAccessEnabled: true + virtualNetworkRules: [ + { + subnet: { + ignoreMissingVnetServiceEndpoint: true + id: nestedDependencies.outputs.subnetResourceId + } + } + ] + ipRules: [ + { + ipMask: '10.0.1.0/32' + action: 'Allow' + } + { + ipMask: '10.0.2.0/32' + action: 'Allow' + } + ] + } + authorizationRules: [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + { + name: 'AnotherKey' + rights: [ + 'Listen' + 'Send' + ] + } + ] + hybridConnections: [ + { + name: '${namePrefix}${serviceShort}hc001' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + userMetadata: '[{"key":"endpoint","value":"db-server.constoso.com:1433"}]' + } + ] + wcfRelays: [ + { + name: '${namePrefix}${serviceShort}wcf001' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + relayType: 'NetTcp' + } + ] + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + privateEndpoints: [ + { + service: 'namespace' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + } + ] + } +}] diff --git a/avm/res/relay/namespace/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/relay/namespace/tests/e2e/waf-aligned/dependencies.bicep new file mode 100644 index 0000000000..c63bafc918 --- /dev/null +++ b/avm/res/relay/namespace/tests/e2e/waf-aligned/dependencies.bicep @@ -0,0 +1,49 @@ +@description('Optional. The location to deploy resources 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@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + } + } + ] + } +} + +resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { + name: 'privatelink.servicebus.windows.net' + location: 'global' + + resource virtualNetworkLinks 'virtualNetworkLinks@2020-06-01' = { + name: '${virtualNetwork.name}-vnetlink' + location: 'global' + properties: { + virtualNetwork: { + id: virtualNetwork.id + } + registrationEnabled: false + } + } +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The resource ID of the created Private DNS Zone.') +output privateDNSZoneResourceId string = privateDNSZone.id diff --git a/avm/res/relay/namespace/tests/e2e/waf-aligned/main.test.bicep b/avm/res/relay/namespace/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..c521d54f70 --- /dev/null +++ b/avm/res/relay/namespace/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,148 @@ +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}-relay.namespaces-${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 = 'rnwaf' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + location: resourceLocation + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-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 + } +} + +// ============== // +// 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 + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + networkRuleSets: { + defaultAction: 'Deny' + trustedServiceAccessEnabled: true + virtualNetworkRules: [ + { + subnet: { + ignoreMissingVnetServiceEndpoint: true + id: nestedDependencies.outputs.subnetResourceId + } + } + ] + ipRules: [ + { + ipMask: '10.0.1.0/32' + action: 'Allow' + } + { + ipMask: '10.0.2.0/32' + action: 'Allow' + } + ] + } + authorizationRules: [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + { + name: 'AnotherKey' + rights: [ + 'Listen' + 'Send' + ] + } + ] + hybridConnections: [ + { + name: '${namePrefix}${serviceShort}hc001' + userMetadata: '[{"key":"endpoint","value":"db-server.constoso.com:1433"}]' + } + ] + wcfRelays: [ + { + name: '${namePrefix}${serviceShort}wcf001' + relayType: 'NetTcp' + } + ] + diagnosticSettings: [ + { + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + privateEndpoints: [ + { + service: 'namespace' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + ] + } +} +] diff --git a/avm/res/relay/namespace/version.json b/avm/res/relay/namespace/version.json new file mode 100644 index 0000000000..83083db694 --- /dev/null +++ b/avm/res/relay/namespace/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.1", + "pathFilters": [ + "./main.json" + ] +} \ No newline at end of file diff --git a/avm/res/relay/namespace/wcf-relay/README.md b/avm/res/relay/namespace/wcf-relay/README.md new file mode 100644 index 0000000000..99816c975d --- /dev/null +++ b/avm/res/relay/namespace/wcf-relay/README.md @@ -0,0 +1,271 @@ +# Relay Namespace WCF Relays `[Microsoft.Relay/namespaces/wcfRelays]` + +This module deploys a Relay Namespace WCF Relay. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [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.Relay/namespaces/wcfRelays` | [2021-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Relay/2021-11-01/namespaces/wcfRelays) | +| `Microsoft.Relay/namespaces/wcfRelays/authorizationRules` | [2021-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Relay/2021-11-01/namespaces/wcfRelays/authorizationRules) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the WCF Relay. | +| [`relayType`](#parameter-relaytype) | string | Type of WCF Relay. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`namespaceName`](#parameter-namespacename) | string | The name of the parent Relay Namespace for the WCF Relay. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`authorizationRules`](#parameter-authorizationrules) | array | Authorization Rules for the WCF Relay. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`requiresClientAuthorization`](#parameter-requiresclientauthorization) | bool | A value indicating if this relay requires client authorization. | +| [`requiresTransportSecurity`](#parameter-requirestransportsecurity) | bool | A value indicating if this relay requires transport security. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`userMetadata`](#parameter-usermetadata) | string | User-defined string data for the WCF Relay. | + +### Parameter: `name` + +Name of the WCF Relay. + +- Required: Yes +- Type: string + +### Parameter: `relayType` + +Type of WCF Relay. + +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'Http' + 'NetTcp' + ] + ``` + +### Parameter: `namespaceName` + +The name of the parent Relay Namespace for the WCF Relay. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `authorizationRules` + +Authorization Rules for the WCF Relay. + +- Required: No +- Type: array +- Default: + ```Bicep + [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + { + name: 'defaultListener' + rights: [ + 'Listen' + ] + } + { + name: 'defaultSender' + rights: [ + 'Send' + ] + } + ] + ``` + +### 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: `requiresClientAuthorization` + +A value indicating if this relay requires client authorization. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `requiresTransportSecurity` + +A value indicating if this relay requires transport security. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**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. | +| [`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.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `userMetadata` + +User-defined string data for the WCF Relay. + +- Required: No +- Type: string + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed wcf relay. | +| `resourceGroupName` | string | The resource group of the deployed wcf relay. | +| `resourceId` | string | The resource ID of the deployed wcf relay. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/relay/namespace/wcf-relay/authorization-rule/README.md b/avm/res/relay/namespace/wcf-relay/authorization-rule/README.md new file mode 100644 index 0000000000..b573cc4003 --- /dev/null +++ b/avm/res/relay/namespace/wcf-relay/authorization-rule/README.md @@ -0,0 +1,92 @@ +# WCF Relay Authorization Rules `[Microsoft.Relay/namespaces/wcfRelays/authorizationRules]` + +This module deploys a WCF Relay Authorization Rule. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Relay/namespaces/wcfRelays/authorizationRules` | [2021-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Relay/2021-11-01/namespaces/wcfRelays/authorizationRules) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | The name of the authorization rule. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`namespaceName`](#parameter-namespacename) | string | The name of the parent Relay Namespace. Required if the template is used in a standalone deployment. | +| [`wcfRelayName`](#parameter-wcfrelayname) | string | The name of the parent Relay Namespace WCF Relay. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`rights`](#parameter-rights) | array | The rights associated with the rule. | + +### Parameter: `name` + +The name of the authorization rule. + +- Required: Yes +- Type: string + +### Parameter: `namespaceName` + +The name of the parent Relay Namespace. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `wcfRelayName` + +The name of the parent Relay Namespace WCF Relay. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `rights` + +The rights associated with the rule. + +- Required: No +- Type: array +- Default: `[]` +- Allowed: + ```Bicep + [ + 'Listen' + 'Manage' + 'Send' + ] + ``` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the authorization rule. | +| `resourceGroupName` | string | The name of the Resource Group the authorization rule was created in. | +| `resourceId` | string | The Resource ID of the authorization rule. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/relay/namespace/wcf-relay/authorization-rule/main.bicep b/avm/res/relay/namespace/wcf-relay/authorization-rule/main.bicep new file mode 100644 index 0000000000..9374cd4ca7 --- /dev/null +++ b/avm/res/relay/namespace/wcf-relay/authorization-rule/main.bicep @@ -0,0 +1,45 @@ +metadata name = 'WCF Relay Authorization Rules' +metadata description = 'This module deploys a WCF Relay Authorization Rule.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. The name of the authorization rule.') +param name string + +@description('Conditional. The name of the parent Relay Namespace. Required if the template is used in a standalone deployment.') +param namespaceName string + +@description('Conditional. The name of the parent Relay Namespace WCF Relay. Required if the template is used in a standalone deployment.') +param wcfRelayName string + +@description('Optional. The rights associated with the rule.') +@allowed([ + 'Listen' + 'Manage' + 'Send' +]) +param rights array = [] + +resource namespace 'Microsoft.Relay/namespaces@2021-11-01' existing = { + name: namespaceName + + resource wcfRelay 'wcfRelays@2021-11-01' existing = { + name: wcfRelayName + } +} + +resource authorizationRule 'Microsoft.Relay/namespaces/wcfRelays/authorizationRules@2021-11-01' = { + name: name + parent: namespace::wcfRelay + properties: { + rights: rights + } +} + +@description('The name of the authorization rule.') +output name string = authorizationRule.name + +@description('The Resource ID of the authorization rule.') +output resourceId string = authorizationRule.id + +@description('The name of the Resource Group the authorization rule was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/avm/res/relay/namespace/wcf-relay/authorization-rule/main.json b/avm/res/relay/namespace/wcf-relay/authorization-rule/main.json new file mode 100644 index 0000000000..0ca3d617d4 --- /dev/null +++ b/avm/res/relay/namespace/wcf-relay/authorization-rule/main.json @@ -0,0 +1,79 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.26.54.24096", + "templateHash": "8736725131114489503" + }, + "name": "WCF Relay Authorization Rules", + "description": "This module deploys a WCF Relay Authorization Rule.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the authorization rule." + } + }, + "namespaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Relay Namespace. Required if the template is used in a standalone deployment." + } + }, + "wcfRelayName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Relay Namespace WCF Relay. Required if the template is used in a standalone deployment." + } + }, + "rights": { + "type": "array", + "defaultValue": [], + "allowedValues": [ + "Listen", + "Manage", + "Send" + ], + "metadata": { + "description": "Optional. The rights associated with the rule." + } + } + }, + "resources": [ + { + "type": "Microsoft.Relay/namespaces/wcfRelays/authorizationRules", + "apiVersion": "2021-11-01", + "name": "[format('{0}/{1}/{2}', parameters('namespaceName'), parameters('wcfRelayName'), parameters('name'))]", + "properties": { + "rights": "[parameters('rights')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the authorization rule." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The Resource ID of the authorization rule." + }, + "value": "[resourceId('Microsoft.Relay/namespaces/wcfRelays/authorizationRules', parameters('namespaceName'), parameters('wcfRelayName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the authorization rule was created in." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/relay/namespace/wcf-relay/authorization-rule/version.json b/avm/res/relay/namespace/wcf-relay/authorization-rule/version.json new file mode 100644 index 0000000000..7fa401bdf7 --- /dev/null +++ b/avm/res/relay/namespace/wcf-relay/authorization-rule/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/res/relay/namespace/wcf-relay/main.bicep b/avm/res/relay/namespace/wcf-relay/main.bicep new file mode 100644 index 0000000000..702be53d40 --- /dev/null +++ b/avm/res/relay/namespace/wcf-relay/main.bicep @@ -0,0 +1,180 @@ +metadata name = 'Relay Namespace WCF Relays' +metadata description = 'This module deploys a Relay Namespace WCF Relay.' +metadata owner = 'Azure/module-maintainers' + +@description('Conditional. The name of the parent Relay Namespace for the WCF Relay. Required if the template is used in a standalone deployment.') +@minLength(6) +@maxLength(50) +param namespaceName string + +@description('Required. Name of the WCF Relay.') +@minLength(6) +@maxLength(50) +param name string + +@allowed([ + 'Http' + 'NetTcp' +]) +@description('Required. Type of WCF Relay.') +param relayType string + +@description('Optional. A value indicating if this relay requires client authorization.') +param requiresClientAuthorization bool = true + +@description('Optional. A value indicating if this relay requires transport security.') +param requiresTransportSecurity bool = true + +@description('Optional. User-defined string data for the WCF Relay.') +param userMetadata string? + +@description('Optional. Authorization Rules for the WCF Relay.') +param authorizationRules array = [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + { + name: 'defaultListener' + rights: [ + 'Listen' + ] + } + { + name: 'defaultSender' + rights: [ + 'Send' + ] + } +] + +@description('Optional. The lock settings of the service.') +param lock lockType + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +var builtInRoleNames = { + 'Azure Relay Listener': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '26e0b698-aa6d-4085-9386-aadae190014d' + ) + 'Azure Relay Owner': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '2787bf04-f1f5-4bfe-8383-c8a24483ee38' + ) + 'Azure Relay Sender': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '26baccc8-eea7-41f1-98f4-1762cc7f685d' + ) + 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 (Preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' + ) + 'User Access Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + ) +} + +resource namespace 'Microsoft.Relay/namespaces@2021-11-01' existing = { + name: namespaceName +} + +resource wcfRelay 'Microsoft.Relay/namespaces/wcfRelays@2021-11-01' = { + name: name + parent: namespace + properties: { + relayType: relayType + requiresClientAuthorization: requiresClientAuthorization + requiresTransportSecurity: requiresTransportSecurity + userMetadata: userMetadata + } +} + +module wcfRelay_authorizationRules 'authorization-rule/main.bicep' = [ +for (authorizationRule, index) in authorizationRules: { + name: '${deployment().name}-AuthorizationRule-${index}' + params: { + namespaceName: namespaceName + wcfRelayName: wcfRelay.name + name: authorizationRule.name + rights: authorizationRule.?rights + } +} +] + +resource wcfRelay_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: wcfRelay +} + +resource wcfRelay_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(wcfRelay.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: wcfRelay +} +] + +@description('The name of the deployed wcf relay.') +output name string = wcfRelay.name + +@description('The resource ID of the deployed wcf relay.') +output resourceId string = wcfRelay.id + +@description('The resource group of the deployed wcf relay.') +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('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/relay/namespace/wcf-relay/main.json b/avm/res/relay/namespace/wcf-relay/main.json new file mode 100644 index 0000000000..d4d49648fc --- /dev/null +++ b/avm/res/relay/namespace/wcf-relay/main.json @@ -0,0 +1,401 @@ +{ + "$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.26.54.24096", + "templateHash": "9397973991776922121" + }, + "name": "Relay Namespace WCF Relays", + "description": "This module deploys a Relay Namespace WCF Relay.", + "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": { + "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": { + "namespaceName": { + "type": "string", + "minLength": 6, + "maxLength": 50, + "metadata": { + "description": "Conditional. The name of the parent Relay Namespace for the WCF Relay. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "minLength": 6, + "maxLength": 50, + "metadata": { + "description": "Required. Name of the WCF Relay." + } + }, + "relayType": { + "type": "string", + "allowedValues": [ + "Http", + "NetTcp" + ], + "metadata": { + "description": "Required. Type of WCF Relay." + } + }, + "requiresClientAuthorization": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. A value indicating if this relay requires client authorization." + } + }, + "requiresTransportSecurity": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. A value indicating if this relay requires transport security." + } + }, + "userMetadata": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. User-defined string data for the WCF Relay." + } + }, + "authorizationRules": { + "type": "array", + "defaultValue": [ + { + "name": "RootManageSharedAccessKey", + "rights": [ + "Listen", + "Manage", + "Send" + ] + }, + { + "name": "defaultListener", + "rights": [ + "Listen" + ] + }, + { + "name": "defaultSender", + "rights": [ + "Send" + ] + } + ], + "metadata": { + "description": "Optional. Authorization Rules for the WCF Relay." + } + }, + "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": { + "builtInRoleNames": { + "Azure Relay Listener": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '26e0b698-aa6d-4085-9386-aadae190014d')]", + "Azure Relay Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2787bf04-f1f5-4bfe-8383-c8a24483ee38')]", + "Azure Relay Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '26baccc8-eea7-41f1-98f4-1762cc7f685d')]", + "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 (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "namespace": { + "existing": true, + "type": "Microsoft.Relay/namespaces", + "apiVersion": "2021-11-01", + "name": "[parameters('namespaceName')]" + }, + "wcfRelay": { + "type": "Microsoft.Relay/namespaces/wcfRelays", + "apiVersion": "2021-11-01", + "name": "[format('{0}/{1}', parameters('namespaceName'), parameters('name'))]", + "properties": { + "relayType": "[parameters('relayType')]", + "requiresClientAuthorization": "[parameters('requiresClientAuthorization')]", + "requiresTransportSecurity": "[parameters('requiresTransportSecurity')]", + "userMetadata": "[parameters('userMetadata')]" + }, + "dependsOn": [ + "namespace" + ] + }, + "wcfRelay_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.Relay/namespaces/{0}/wcfRelays/{1}', parameters('namespaceName'), 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": [ + "wcfRelay" + ] + }, + "wcfRelay_roleAssignments": { + "copy": { + "name": "wcfRelay_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Relay/namespaces/{0}/wcfRelays/{1}', parameters('namespaceName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Relay/namespaces/wcfRelays', parameters('namespaceName'), 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": [ + "wcfRelay" + ] + }, + "wcfRelay_authorizationRules": { + "copy": { + "name": "wcfRelay_authorizationRules", + "count": "[length(parameters('authorizationRules'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-AuthorizationRule-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "namespaceName": { + "value": "[parameters('namespaceName')]" + }, + "wcfRelayName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('authorizationRules')[copyIndex()].name]" + }, + "rights": { + "value": "[tryGet(parameters('authorizationRules')[copyIndex()], 'rights')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.26.54.24096", + "templateHash": "8736725131114489503" + }, + "name": "WCF Relay Authorization Rules", + "description": "This module deploys a WCF Relay Authorization Rule.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the authorization rule." + } + }, + "namespaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Relay Namespace. Required if the template is used in a standalone deployment." + } + }, + "wcfRelayName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Relay Namespace WCF Relay. Required if the template is used in a standalone deployment." + } + }, + "rights": { + "type": "array", + "defaultValue": [], + "allowedValues": [ + "Listen", + "Manage", + "Send" + ], + "metadata": { + "description": "Optional. The rights associated with the rule." + } + } + }, + "resources": [ + { + "type": "Microsoft.Relay/namespaces/wcfRelays/authorizationRules", + "apiVersion": "2021-11-01", + "name": "[format('{0}/{1}/{2}', parameters('namespaceName'), parameters('wcfRelayName'), parameters('name'))]", + "properties": { + "rights": "[parameters('rights')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the authorization rule." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The Resource ID of the authorization rule." + }, + "value": "[resourceId('Microsoft.Relay/namespaces/wcfRelays/authorizationRules', parameters('namespaceName'), parameters('wcfRelayName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the authorization rule was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "wcfRelay" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed wcf relay." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed wcf relay." + }, + "value": "[resourceId('Microsoft.Relay/namespaces/wcfRelays', parameters('namespaceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed wcf relay." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file From 89f92f0c04ff731a2757721e310c7a52ae4853d7 Mon Sep 17 00:00:00 2001 From: Kris Baranek Date: Sat, 23 Mar 2024 00:32:15 +0100 Subject: [PATCH 56/73] fix: Patch of `avm/res/relay/namespace` to enforce the publishing (#1394) ## Description Patch of `avm/res/relay/namespace` to enforce the publishing ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.relay.namespace](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.relay.namespace.yml/badge.svg?branch=users%2Fkrbar%2FrelayFix)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.relay.namespace.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [x] Azure Verified Module updates: - [x] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [x] I have run `Set-AVMModule` locally to generate the supporting module files. - [x] My corresponding pipelines / checks run clean and green without any errors or warnings --- avm/res/relay/namespace/README.md | 10 +++++----- avm/res/relay/namespace/main.bicep | 2 +- avm/res/relay/namespace/main.json | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/avm/res/relay/namespace/README.md b/avm/res/relay/namespace/README.md index 3a4056a67d..36ec70114b 100644 --- a/avm/res/relay/namespace/README.md +++ b/avm/res/relay/namespace/README.md @@ -56,7 +56,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module namespace 'br/public:avm/res/relay/namespace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-rnmin' + name: 'namespaceDeployment' params: { // Required parameters name: 'rnmin001' @@ -104,7 +104,7 @@ This instance deploys the module with most of its features enabled. ```bicep module namespace 'br/public:avm/res/relay/namespace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-rnmax' + name: 'namespaceDeployment' params: { // Required parameters name: 'rnmax001' @@ -424,7 +424,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module namespace 'br/public:avm/res/relay/namespace:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-rnwaf' + name: 'namespaceDeployment' params: { // Required parameters name: 'rnwaf001' @@ -644,7 +644,7 @@ module namespace 'br/public:avm/res/relay/namespace:' = { | Parameter | Type | Description | | :-- | :-- | :-- | -| [`authorizationRules`](#parameter-authorizationrules) | array | Authorization Rules for the Relay namespace. | +| [`authorizationRules`](#parameter-authorizationrules) | array | Authorization Rules for the Relay Namespace. | | [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`hybridConnections`](#parameter-hybridconnections) | array | The hybrid connections to create in the relay namespace. | @@ -666,7 +666,7 @@ Name of the Relay Namespace. ### Parameter: `authorizationRules` -Authorization Rules for the Relay namespace. +Authorization Rules for the Relay Namespace. - Required: No - Type: array diff --git a/avm/res/relay/namespace/main.bicep b/avm/res/relay/namespace/main.bicep index 5ec2aabfb6..456bb998fb 100644 --- a/avm/res/relay/namespace/main.bicep +++ b/avm/res/relay/namespace/main.bicep @@ -16,7 +16,7 @@ param location string = resourceGroup().location ]) param skuName string = 'Standard' -@description('Optional. Authorization Rules for the Relay namespace.') +@description('Optional. Authorization Rules for the Relay Namespace.') param authorizationRules array = [ { name: 'RootManageSharedAccessKey' diff --git a/avm/res/relay/namespace/main.json b/avm/res/relay/namespace/main.json index 9ede75558f..356dbb9a31 100644 --- a/avm/res/relay/namespace/main.json +++ b/avm/res/relay/namespace/main.json @@ -447,7 +447,7 @@ } ], "metadata": { - "description": "Optional. Authorization Rules for the Relay namespace." + "description": "Optional. Authorization Rules for the Relay Namespace." } }, "diagnosticSettings": { From 4c54f94325641282f900641c542587106b6dac50 Mon Sep 17 00:00:00 2001 From: Alexander Sehr Date: Mon, 25 Mar 2024 09:08:21 +0100 Subject: [PATCH 57/73] feat: Updated Git tag handling to be more robust (#1399) ## Description - Made sure pipeline fails if git tag is not correcly published - Added post-publishing test that fails if the git tag is not found - Tested fail state locally as having a git tag rejected isn't exactly easy to provoke ## Pipeline Reference | Pipeline | | -------- | | [working run](https://github.com/AlexanderSehr/bicep-registry-modules/actions/runs/8401389568/job/23009717955) | ## Type of Change - [x] Update to CI Environment or utlities (Non-module effecting changes) - [ ] Azure Verified Module updates: - [ ] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation --------- Co-authored-by: Erika Gressi <56914614+eriqua@users.noreply.github.com> --- .../templates/avm-publishModule/action.yml | 7 +++++-- .../publish/Confirm-ModuleIsPublished.ps1 | 18 +++++++++++++++++- .../publish/Publish-ModuleFromPathToPBR.ps1 | 5 +++-- .../publish/helper/New-ModuleReleaseTag.ps1 | 10 +++++++--- 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/.github/actions/templates/avm-publishModule/action.yml b/.github/actions/templates/avm-publishModule/action.yml index 7192a29073..b2470500de 100644 --- a/.github/actions/templates/avm-publishModule/action.yml +++ b/.github/actions/templates/avm-publishModule/action.yml @@ -67,8 +67,10 @@ runs: Write-Verbose ($functionInput | ConvertTo-Json | Out-String) -Verbose if($publishOutputs = Publish-ModuleFromPathToPBR @functionInput -Verbose) { - Write-Output ('{0}={1}' -f 'version', $publishOutputs.version) >> $env:GITHUB_OUTPUT - Write-Output ('{0}={1}' -f 'publishedModuleName', $publishOutputs.publishedModuleName) >> $env:GITHUB_OUTPUT + $publishOutputs.Keys | Foreach-Object { + Write-Verbose ('Passing pipeline variable [{0}] with value [{1}]' -f $_, $publishOutputs.$_) -Verbose + Write-Output ('{0}={1}' -f $_, $publishOutputs.$_) >> $env:GITHUB_OUTPUT + } } Write-Output '::endgroup::' @@ -88,6 +90,7 @@ runs: $functionInput = @{ Version = "${{ steps.publish_step.outputs.version }}" PublishedModuleName = "${{ steps.publish_step.outputs.publishedModuleName }}" + GitTagName = "${{ steps.publish_step.outputs.gitTagName }}" } Write-Verbose "Invoke function with" -Verbose diff --git a/avm/utilities/pipelines/publish/Confirm-ModuleIsPublished.ps1 b/avm/utilities/pipelines/publish/Confirm-ModuleIsPublished.ps1 index 22b8045560..645b5adc91 100644 --- a/avm/utilities/pipelines/publish/Confirm-ModuleIsPublished.ps1 +++ b/avm/utilities/pipelines/publish/Confirm-ModuleIsPublished.ps1 @@ -11,6 +11,9 @@ Mandatory. The version of the module to check for. For example: '0.2.0' .PARAMETER PublishedModuleName Mandatory. The path of the module to check for. For example: 'avm/res/key-vault/vault' +.PARAMETER GitTagName +Mandatory. The tag name of the module's git tag to check for. For example: 'avm/res/event-hub/namespace/0.2.0' + .EXAMPLE Confirm-ModuleIsPublished -Version '0.2.0' -PublishedModuleName 'avm/res/key-vault/vault' -Verbose @@ -24,7 +27,10 @@ function Confirm-ModuleIsPublished { [string] $Version, [Parameter(Mandatory)] - [string] $PublishedModuleName + [string] $PublishedModuleName, + + [Parameter(Mandatory)] + [string] $GitTagName ) $baseUrl = 'https://mcr.microsoft.com/v2' @@ -36,6 +42,16 @@ function Confirm-ModuleIsPublished { $retry_seconds = 60 $index = 0 + ####################################### + ## Confirm module tag is created ## + ####################################### + $existingTag = git ls-remote --tags origin $GitTagName + if (-not $existingTag) { + throw "Tag [$GitTagName] was not successfully created. Please review." + } else { + Write-Verbose "Passed: Found Git tag [$GitTagName]" -Verbose + } + ##################################### ## Confirm module is published ## ##################################### diff --git a/avm/utilities/pipelines/publish/Publish-ModuleFromPathToPBR.ps1 b/avm/utilities/pipelines/publish/Publish-ModuleFromPathToPBR.ps1 index d66f55502f..9767b14faf 100644 --- a/avm/utilities/pipelines/publish/Publish-ModuleFromPathToPBR.ps1 +++ b/avm/utilities/pipelines/publish/Publish-ModuleFromPathToPBR.ps1 @@ -61,10 +61,10 @@ function Publish-ModuleFromPathToPBR { $publishedModuleName = Get-BRMRepositoryName -TemplateFilePath $TemplateFilePath # 4.Create release tag - $tagName = New-ModuleReleaseTag -ModuleFolderPath $moduleFolderPath -TargetVersion $targetVersion + $gitTagName = New-ModuleReleaseTag -ModuleFolderPath $moduleFolderPath -TargetVersion $targetVersion # 5. Get the documentation link - $documentationUri = Get-ModuleReadmeLink -TagName $tagName -ModuleFolderPath $moduleFolderPath + $documentationUri = Get-ModuleReadmeLink -TagName $gitTagName -ModuleFolderPath $moduleFolderPath # 6. Replace telemetry version value (in Bicep) $tokenConfiguration = @{ @@ -108,5 +108,6 @@ function Publish-ModuleFromPathToPBR { return @{ version = $targetVersion publishedModuleName = $publishedModuleName + gitTagName = $gitTagName } } diff --git a/avm/utilities/pipelines/publish/helper/New-ModuleReleaseTag.ps1 b/avm/utilities/pipelines/publish/helper/New-ModuleReleaseTag.ps1 index a1d1f8ab23..d8bfe0b8cc 100644 --- a/avm/utilities/pipelines/publish/helper/New-ModuleReleaseTag.ps1 +++ b/avm/utilities/pipelines/publish/helper/New-ModuleReleaseTag.ps1 @@ -38,16 +38,16 @@ function New-ModuleReleaseTag { $wellFormattedTag = git check-ref-format --normalize $tagName if (-not $wellFormattedTag) { throw "Tag [$tagName] is not well formatted." - # TODO: Handle exception if tag not formatted correctly } # 3 Check tag not already existing $existingTag = git ls-remote --tags origin $tagName if ($existingTag) { - throw "Tag [$tagName] already exists" - # TODO: Handle exception if tag already existing + Write-Verbose "Tag [$tagName] already exists" -Verbose + return $tagName } + # 3 Create local tag Write-Verbose "Creating release tag: [$tagName]" -Verbose git tag $tagName @@ -56,6 +56,10 @@ function New-ModuleReleaseTag { Write-Verbose "Publishing release tag: [$tagName]" -Verbose git push origin $tagName + if ($LASTEXITCODE -ne 0) { + throw 'Git Tag creation failed. Please review error log.' + } + # 5 Return tag return $tagName } From 8d70f808a051b4fa179fd5618f57cc61f4c1b782 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Barab=C3=A1s?= Date: Mon, 25 Mar 2024 02:25:39 -0700 Subject: [PATCH 58/73] chore: Triage automation updates (#1372) # Overview/Summary This PR includes improvements to the issue triage automation. The following prerequisite PR must be merged, before this PR !!! https://github.com/Azure/Azure-Verified-Modules/pull/763 ## This PR fixes/adds/changes/removes 1. Improve each GH policy service rule by explaining what the bot is reacting to, and provide in-context tips. 2. This PR also removes the avmModuleIssueTriage.yml file that hasn't been used since the introduction of the GH actions that automatically notify and assign module owners to issues that are related to the modules they own. ### Example - When opening a new issue image ### Example - When a Type label is added image ### Example - When a response is overdue image ### Breaking Changes n/a ## As part of this Pull Request I have - [x] Read the Contribution Guide and ensured this PR is compliant with the guide - [x] Checked for duplicate [Pull Requests](https://github.com/Azure/Azure-Verified-Modules/pulls) - [ ] Associated it with relevant [GitHub Issues](https://github.com/Azure/Azure-Verified-Modules/issues) or ADO Work Items (Internal Only) - [x] Ensured my code/branch is up-to-date with the latest changes in the `main` [branch](https://github.com/Azure/Azure-Verified-Modules/) - [x] Ensured PR tests are passing - [x] Updated relevant and associated documentation (e.g. Contribution Guide, Docs etc.) --------- Co-authored-by: Jack Tracey <41163455+jtracey93@users.noreply.github.com> --- .github/policies/avmModuleIssueTriage.yml | 2405 --------------------- .github/policies/eventResponder.yml | 49 +- .github/policies/scheduledSearches.yml | 126 +- 3 files changed, 152 insertions(+), 2428 deletions(-) delete mode 100644 .github/policies/avmModuleIssueTriage.yml diff --git a/.github/policies/avmModuleIssueTriage.yml b/.github/policies/avmModuleIssueTriage.yml deleted file mode 100644 index f0592b558a..0000000000 --- a/.github/policies/avmModuleIssueTriage.yml +++ /dev/null @@ -1,2405 +0,0 @@ -id: avmModuleIssueTriage -name: AVM Module Issue Triage -description: AVM Module Issue Triage -resource: repository -disabled: false - -configuration: - resourceManagementConfiguration: - eventResponderTasks: - - description: "AVM-MOD-0001 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/aad/domain-service - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/aad/domain-service` module! - - A member of the @azure/avm-res-aad-domainservice-module-owners-bicep or @azure/avm-res-aad-domainservice-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0002 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/analysis-services/server - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/analysis-services/server` module! - - A member of the @azure/avm-res-analysisservices-server-module-owners-bicep or @azure/avm-res-analysisservices-server-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0003 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/api-management/service - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/api-management/service` module! - - A member of the @azure/avm-res-apimanagement-service-module-owners-bicep or @azure/avm-res-apimanagement-service-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0004 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/app/container-app - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/app/container-app` module! - - A member of the @azure/avm-res-app-containerapp-module-owners-bicep or @azure/avm-res-app-containerapp-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0005 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/app/managed-environment - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/app/managed-environment` module! - - A member of the @azure/avm-res-app-managedenvironment-module-owners-bicep or @azure/avm-res-app-managedenvironment-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0006 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/app-configuration/configuration-store - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/app-configuration/configuration-store` module! - - A member of the @azure/avm-res-appconfiguration-configurationstore-module-owners-bicep or @azure/avm-res-appconfiguration-configurationstore-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0007 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/authorization/lock - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/authorization/lock` module! - - A member of the @azure/avm-res-authorization-lock-module-owners-bicep or @azure/avm-res-authorization-lock-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0008 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/authorization/policy-assignment - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/authorization/policy-assignment` module! - - A member of the @azure/avm-res-authorization-policyassignment-module-owners-bicep or @azure/avm-res-authorization-policyassignment-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0009 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/authorization/policy-definition - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/authorization/policy-definition` module! - - A member of the @azure/avm-res-authorization-policydefinition-module-owners-bicep or @azure/avm-res-authorization-policydefinition-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0010 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/authorization/policy-exemption - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/authorization/policy-exemption` module! - - A member of the @azure/avm-res-authorization-policyexemption-module-owners-bicep or @azure/avm-res-authorization-policyexemption-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0011 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/authorization/policy-set-definition - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/authorization/policy-set-definition` module! - - A member of the @azure/avm-res-authorization-policysetdefinition-module-owners-bicep or @azure/avm-res-authorization-policysetdefinition-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0012 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/authorization/role-assignment - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/authorization/role-assignment` module! - - A member of the @azure/avm-res-authorization-roleassignment-module-owners-bicep or @azure/avm-res-authorization-roleassignment-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0013 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/authorization/role-definition - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/authorization/role-definition` module! - - A member of the @azure/avm-res-authorization-roledefinition-module-owners-bicep or @azure/avm-res-authorization-roledefinition-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0014 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/automation/automation-account - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/automation/automation-account` module! - - A member of the @azure/avm-res-automation-automationaccount-module-owners-bicep or @azure/avm-res-automation-automationaccount-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0015 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/batch/batch-account - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/batch/batch-account` module! - - A member of the @azure/avm-res-batch-batchaccount-module-owners-bicep or @azure/avm-res-batch-batchaccount-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0016 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/cache/redis - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/cache/redis` module! - - A member of the @azure/avm-res-cache-redis-module-owners-bicep or @azure/avm-res-cache-redis-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0017 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/cdn/profile - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/cdn/profile` module! - - A member of the @azure/avm-res-cdn-profile-module-owners-bicep or @azure/avm-res-cdn-profile-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0018 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/cognitive-services/account - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/cognitive-services/account` module! - - A member of the @azure/avm-res-cognitiveservices-account-module-owners-bicep or @azure/avm-res-cognitiveservices-account-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0019 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/compute/availability-set - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/compute/availability-set` module! - - A member of the @azure/avm-res-compute-availabilityset-module-owners-bicep or @azure/avm-res-compute-availabilityset-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0020 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/compute/disk - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/compute/disk` module! - - A member of the @azure/avm-res-compute-disk-module-owners-bicep or @azure/avm-res-compute-disk-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0021 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/compute/disk-encryption-set - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/compute/disk-encryption-set` module! - - A member of the @azure/avm-res-compute-diskencryptionset-module-owners-bicep or @azure/avm-res-compute-diskencryptionset-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0022 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/compute/gallery - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/compute/gallery` module! - - A member of the @azure/avm-res-compute-gallery-module-owners-bicep or @azure/avm-res-compute-gallery-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0023 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/compute/image - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/compute/image` module! - - A member of the @azure/avm-res-compute-image-module-owners-bicep or @azure/avm-res-compute-image-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0024 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/compute/proximity-placement-group - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/compute/proximity-placement-group` module! - - A member of the @azure/avm-res-compute-proximityplacementgroup-module-owners-bicep or @azure/avm-res-compute-proximityplacementgroup-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0025 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/compute/ssh-public-key - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/compute/ssh-public-key` module! - - A member of the @azure/avm-res-compute-sshpublickey-module-owners-bicep or @azure/avm-res-compute-sshpublickey-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0026 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/compute/virtual-machine - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/compute/virtual-machine` module! - - A member of the @azure/avm-res-compute-virtualmachine-module-owners-bicep or @azure/avm-res-compute-virtualmachine-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0027 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/compute/virtual-machine-scale-set - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/compute/virtual-machine-scale-set` module! - - A member of the @azure/avm-res-compute-virtualmachinescaleset-module-owners-bicep or @azure/avm-res-compute-virtualmachinescaleset-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0028 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/consumption/budget - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/consumption/budget` module! - - A member of the @azure/avm-res-consumption-budget-module-owners-bicep or @azure/avm-res-consumption-budget-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0029 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/container-instance/container-group - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/container-instance/container-group` module! - - A member of the @azure/avm-res-containerinstance-containergroup-module-owners-bicep or @azure/avm-res-containerinstance-containergroup-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0030 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/container-registry/registry - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/container-registry/registry` module! - - A member of the @azure/avm-res-containerregistry-registry-module-owners-bicep or @azure/avm-res-containerregistry-registry-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0031 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/container-service/managed-cluster - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/container-service/managed-cluster` module! - - A member of the @azure/avm-res-containerservice-managedcluster-module-owners-bicep or @azure/avm-res-containerservice-managedcluster-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0032 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/databricks/access-connector - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/databricks/access-connector` module! - - A member of the @azure/avm-res-databricks-accessconnector-module-owners-bicep or @azure/avm-res-databricks-accessconnector-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0033 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/databricks/workspace - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/databricks/workspace` module! - - A member of the @azure/avm-res-databricks-workspace-module-owners-bicep or @azure/avm-res-databricks-workspace-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0034 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/data-factory/factory - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/data-factory/factory` module! - - A member of the @azure/avm-res-datafactory-factory-module-owners-bicep or @azure/avm-res-datafactory-factory-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0035 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/data-protection/backup-vault - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/data-protection/backup-vault` module! - - A member of the @azure/avm-res-dataprotection-backupvault-module-owners-bicep or @azure/avm-res-dataprotection-backupvault-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0036 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/db-for-my-sql/flexible-server - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/db-for-my-sql/flexible-server` module! - - A member of the @azure/avm-res-dbformysql-flexibleserver-module-owners-bicep or @azure/avm-res-dbformysql-flexibleserver-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0037 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/db-for-postgre-sql/flexible-server - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/db-for-postgre-sql/flexible-server` module! - - A member of the @azure/avm-res-dbforpostgresql-flexibleserver-module-owners-bicep or @azure/avm-res-dbforpostgresql-flexibleserver-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0038 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/desktop-virtualization/application-group - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/desktop-virtualization/application-group` module! - - A member of the @azure/avm-res-desktopvirtualization-applicationgroup-module-owners-bicep or @azure/avm-res-desktopvirtualization-applicationgroup-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0039 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/desktop-virtualization/host-pool - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/desktop-virtualization/host-pool` module! - - A member of the @azure/avm-res-desktopvirtualization-hostpool-module-owners-bicep or @azure/avm-res-desktopvirtualization-hostpool-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0040 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/desktop-virtualization/scaling-plan - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/desktop-virtualization/scaling-plan` module! - - A member of the @azure/avm-res-desktopvirtualization-scalingplan-module-owners-bicep or @azure/avm-res-desktopvirtualization-scalingplan-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0041 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/desktop-virtualization/workspace - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/desktop-virtualization/workspace` module! - - A member of the @azure/avm-res-desktopvirtualization-workspace-module-owners-bicep or @azure/avm-res-desktopvirtualization-workspace-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0042 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/dev-center/devcenter - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/dev-center/devcenter` module! - - A member of the @azure/avm-res-devcenter-devcenter-module-owners-bicep or @azure/avm-res-devcenter-devcenter-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0043 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/dev-test-lab/lab - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/dev-test-lab/lab` module! - - A member of the @azure/avm-res-devtestlab-lab-module-owners-bicep or @azure/avm-res-devtestlab-lab-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0044 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/digital-twins/digital-twins-instance - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/digital-twins/digital-twins-instance` module! - - A member of the @azure/avm-res-digitaltwins-digitaltwinsinstance-module-owners-bicep or @azure/avm-res-digitaltwins-digitaltwinsinstance-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0045 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/document-db/database-account - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/document-db/database-account` module! - - A member of the @azure/avm-res-documentdb-databaseaccount-module-owners-bicep or @azure/avm-res-documentdb-databaseaccount-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0046 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/event-grid/domain - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/event-grid/domain` module! - - A member of the @azure/avm-res-eventgrid-domain-module-owners-bicep or @azure/avm-res-eventgrid-domain-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0047 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/event-grid/system-topic - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/event-grid/system-topic` module! - - A member of the @azure/avm-res-eventgrid-systemtopic-module-owners-bicep or @azure/avm-res-eventgrid-systemtopic-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0048 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/event-grid/topic - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/event-grid/topic` module! - - A member of the @azure/avm-res-eventgrid-topic-module-owners-bicep or @azure/avm-res-eventgrid-topic-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0049 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/event-hub/namespace - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/event-hub/namespace` module! - - A member of the @azure/avm-res-eventhub-namespace-module-owners-bicep or @azure/avm-res-eventhub-namespace-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0050 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/health-bot/health-bot - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/health-bot/health-bot` module! - - A member of the @azure/avm-res-healthbot-healthbot-module-owners-bicep or @azure/avm-res-healthbot-healthbot-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0051 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/healthcare-apis/workspace - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/healthcare-apis/workspace` module! - - A member of the @azure/avm-res-healthcareapis-workspace-module-owners-bicep or @azure/avm-res-healthcareapis-workspace-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0052 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/insights/action-group - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/insights/action-group` module! - - A member of the @azure/avm-res-insights-actiongroup-module-owners-bicep or @azure/avm-res-insights-actiongroup-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0053 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/insights/activity-log-alert - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/insights/activity-log-alert` module! - - A member of the @azure/avm-res-insights-activitylogalert-module-owners-bicep or @azure/avm-res-insights-activitylogalert-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0054 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/insights/component - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/insights/component` module! - - A member of the @azure/avm-res-insights-component-module-owners-bicep or @azure/avm-res-insights-component-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0055 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/insights/data-collection-endpoint - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/insights/data-collection-endpoint` module! - - A member of the @azure/avm-res-insights-datacollectionendpoint-module-owners-bicep or @azure/avm-res-insights-datacollectionendpoint-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0056 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/insights/data-collection-rule - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/insights/data-collection-rule` module! - - A member of the @azure/avm-res-insights-datacollectionrule-module-owners-bicep or @azure/avm-res-insights-datacollectionrule-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0057 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/insights/diagnostic-setting - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/insights/diagnostic-setting` module! - - A member of the @azure/avm-res-insights-diagnosticsetting-module-owners-bicep or @azure/avm-res-insights-diagnosticsetting-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0058 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/insights/metric-alert - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/insights/metric-alert` module! - - A member of the @azure/avm-res-insights-metricalert-module-owners-bicep or @azure/avm-res-insights-metricalert-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0059 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/insights/private-link-scope - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/insights/private-link-scope` module! - - A member of the @azure/avm-res-insights-privatelinkscope-module-owners-bicep or @azure/avm-res-insights-privatelinkscope-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0060 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/insights/scheduled-query-rule - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/insights/scheduled-query-rule` module! - - A member of the @azure/avm-res-insights-scheduledqueryrule-module-owners-bicep or @azure/avm-res-insights-scheduledqueryrule-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0061 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/insights/webtest - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/insights/webtest` module! - - A member of the @azure/avm-res-insights-webtest-module-owners-bicep or @azure/avm-res-insights-webtest-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0062 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/key-vault/vault - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/key-vault/vault` module! - - A member of the @azure/avm-res-keyvault-vault-module-owners-bicep or @azure/avm-res-keyvault-vault-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0063 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/kubernetes-configuration/extension - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/kubernetes-configuration/extension` module! - - A member of the @azure/avm-res-kubernetesconfiguration-extension-module-owners-bicep or @azure/avm-res-kubernetesconfiguration-extension-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0064 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/kubernetes-configuration/flux-configuration - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/kubernetes-configuration/flux-configuration` module! - - A member of the @azure/avm-res-kubernetesconfiguration-fluxconfiguration-module-owners-bicep or @azure/avm-res-kubernetesconfiguration-fluxconfiguration-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0065 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/load-test-service/load-test - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/load-test-service/load-test` module! - - A member of the @azure/avm-res-loadtestservice-loadtest-module-owners-bicep or @azure/avm-res-loadtestservice-loadtest-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0066 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/logic/workflow - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/logic/workflow` module! - - A member of the @azure/avm-res-logic-workflow-module-owners-bicep or @azure/avm-res-logic-workflow-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0067 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/machine-learning-services/workspace - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/machine-learning-services/workspace` module! - - A member of the @azure/avm-res-machinelearningservices-workspace-module-owners-bicep or @azure/avm-res-machinelearningservices-workspace-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0068 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/maintenance/maintenance-configuration - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/maintenance/maintenance-configuration` module! - - A member of the @azure/avm-res-maintenance-maintenanceconfiguration-module-owners-bicep or @azure/avm-res-maintenance-maintenanceconfiguration-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0069 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/managed-identity/user-assigned-identity - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/managed-identity/user-assigned-identity` module! - - A member of the @azure/avm-res-managedidentity-userassignedidentity-module-owners-bicep or @azure/avm-res-managedidentity-userassignedidentity-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0070 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/managed-services/registration-definition - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/managed-services/registration-definition` module! - - A member of the @azure/avm-res-managedservices-registrationdefinition-module-owners-bicep or @azure/avm-res-managedservices-registrationdefinition-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0071 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/management/management-group - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/management/management-group` module! - - A member of the @azure/avm-res-management-managementgroup-module-owners-bicep or @azure/avm-res-management-managementgroup-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0072 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/net-app/net-app-account - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/net-app/net-app-account` module! - - A member of the @azure/avm-res-netapp-netappaccount-module-owners-bicep or @azure/avm-res-netapp-netappaccount-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0073 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/application-gateway - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/application-gateway` module! - - A member of the @azure/avm-res-network-applicationgateway-module-owners-bicep or @azure/avm-res-network-applicationgateway-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0074 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/application-gateway-web-application-firewall-policy - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/application-gateway-web-application-firewall-policy` module! - - A member of the @azure/avm-res-network-applicationgatewaywebapplicationfirewallpolicy-module-owners-bicep or @azure/avm-res-network-applicationgatewaywebapplicationfirewallpolicy-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0075 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/application-security-group - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/application-security-group` module! - - A member of the @azure/avm-res-network-applicationsecuritygroup-module-owners-bicep or @azure/avm-res-network-applicationsecuritygroup-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0076 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/azure-firewall - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/azure-firewall` module! - - A member of the @azure/avm-res-network-azurefirewall-module-owners-bicep or @azure/avm-res-network-azurefirewall-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0077 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/bastion-host - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/bastion-host` module! - - A member of the @azure/avm-res-network-bastionhost-module-owners-bicep or @azure/avm-res-network-bastionhost-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0078 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/connection - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/connection` module! - - A member of the @azure/avm-res-network-connection-module-owners-bicep or @azure/avm-res-network-connection-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0079 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/ddos-protection-plan - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/ddos-protection-plan` module! - - A member of the @azure/avm-res-network-ddosprotectionplan-module-owners-bicep or @azure/avm-res-network-ddosprotectionplan-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0080 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/dns-forwarding-ruleset - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/dns-forwarding-ruleset` module! - - A member of the @azure/avm-res-network-dnsforwardingruleset-module-owners-bicep or @azure/avm-res-network-dnsforwardingruleset-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0081 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/dns-resolver - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/dns-resolver` module! - - A member of the @azure/avm-res-network-dnsresolver-module-owners-bicep or @azure/avm-res-network-dnsresolver-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0082 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/dns-zone - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/dns-zone` module! - - A member of the @azure/avm-res-network-dnszone-module-owners-bicep or @azure/avm-res-network-dnszone-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0083 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/express-route-circuit - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/express-route-circuit` module! - - A member of the @azure/avm-res-network-expressroutecircuit-module-owners-bicep or @azure/avm-res-network-expressroutecircuit-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0084 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/express-route-gateway - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/express-route-gateway` module! - - A member of the @azure/avm-res-network-expressroutegateway-module-owners-bicep or @azure/avm-res-network-expressroutegateway-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0085 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/firewall-policy - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/firewall-policy` module! - - A member of the @azure/avm-res-network-firewallpolicy-module-owners-bicep or @azure/avm-res-network-firewallpolicy-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0086 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/front-door - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/front-door` module! - - A member of the @azure/avm-res-network-frontdoor-module-owners-bicep or @azure/avm-res-network-frontdoor-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0087 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/front-door-web-application-firewall-policy - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/front-door-web-application-firewall-policy` module! - - A member of the @azure/avm-res-network-frontdoorwebapplicationfirewallpolicy-module-owners-bicep or @azure/avm-res-network-frontdoorwebapplicationfirewallpolicy-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0088 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/ip-group - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/ip-group` module! - - A member of the @azure/avm-res-network-ipgroup-module-owners-bicep or @azure/avm-res-network-ipgroup-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0089 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/load-balancer - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/load-balancer` module! - - A member of the @azure/avm-res-network-loadbalancer-module-owners-bicep or @azure/avm-res-network-loadbalancer-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0090 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/local-network-gateway - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/local-network-gateway` module! - - A member of the @azure/avm-res-network-localnetworkgateway-module-owners-bicep or @azure/avm-res-network-localnetworkgateway-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0091 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/nat-gateway - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/nat-gateway` module! - - A member of the @azure/avm-res-network-natgateway-module-owners-bicep or @azure/avm-res-network-natgateway-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0092 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/network-interface - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/network-interface` module! - - A member of the @azure/avm-res-network-networkinterface-module-owners-bicep or @azure/avm-res-network-networkinterface-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0093 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/network-manager - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/network-manager` module! - - A member of the @azure/avm-res-network-networkmanager-module-owners-bicep or @azure/avm-res-network-networkmanager-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0094 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/network-security-group - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/network-security-group` module! - - A member of the @azure/avm-res-network-networksecuritygroup-module-owners-bicep or @azure/avm-res-network-networksecuritygroup-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0095 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/network-watcher - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/network-watcher` module! - - A member of the @azure/avm-res-network-networkwatcher-module-owners-bicep or @azure/avm-res-network-networkwatcher-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0096 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/private-dns-zone - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/private-dns-zone` module! - - A member of the @azure/avm-res-network-privatednszone-module-owners-bicep or @azure/avm-res-network-privatednszone-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0097 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/private-endpoint - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/private-endpoint` module! - - A member of the @azure/avm-res-network-privateendpoint-module-owners-bicep or @azure/avm-res-network-privateendpoint-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0098 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/private-link-service - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/private-link-service` module! - - A member of the @azure/avm-res-network-privatelinkservice-module-owners-bicep or @azure/avm-res-network-privatelinkservice-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0099 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/public-ip-address - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/public-ip-address` module! - - A member of the @azure/avm-res-network-publicipaddress-module-owners-bicep or @azure/avm-res-network-publicipaddress-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0100 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/public-ip-prefix - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/public-ip-prefix` module! - - A member of the @azure/avm-res-network-publicipprefix-module-owners-bicep or @azure/avm-res-network-publicipprefix-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0101 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/route-table - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/route-table` module! - - A member of the @azure/avm-res-network-routetable-module-owners-bicep or @azure/avm-res-network-routetable-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0102 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/service-endpoint-policy - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/service-endpoint-policy` module! - - A member of the @azure/avm-res-network-serviceendpointpolicy-module-owners-bicep or @azure/avm-res-network-serviceendpointpolicy-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0103 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/trafficmanagerprofile - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/trafficmanagerprofile` module! - - A member of the @azure/avm-res-network-trafficmanagerprofile-module-owners-bicep or @azure/avm-res-network-trafficmanagerprofile-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0104 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/virtual-hub - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/virtual-hub` module! - - A member of the @azure/avm-res-network-virtualhub-module-owners-bicep or @azure/avm-res-network-virtualhub-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0105 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/virtual-network - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/virtual-network` module! - - A member of the @azure/avm-res-network-virtualnetwork-module-owners-bicep or @azure/avm-res-network-virtualnetwork-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0106 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/virtual-network-gateway - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/virtual-network-gateway` module! - - A member of the @azure/avm-res-network-virtualnetworkgateway-module-owners-bicep or @azure/avm-res-network-virtualnetworkgateway-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0107 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/virtual-wan - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/virtual-wan` module! - - A member of the @azure/avm-res-network-virtualwan-module-owners-bicep or @azure/avm-res-network-virtualwan-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0108 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/vpn-gateway - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/vpn-gateway` module! - - A member of the @azure/avm-res-network-vpngateway-module-owners-bicep or @azure/avm-res-network-vpngateway-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0109 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/network/vpn-site - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/network/vpn-site` module! - - A member of the @azure/avm-res-network-vpnsite-module-owners-bicep or @azure/avm-res-network-vpnsite-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0110 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/operational-insights/workspace - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/operational-insights/workspace` module! - - A member of the @azure/avm-res-operationalinsights-workspace-module-owners-bicep or @azure/avm-res-operationalinsights-workspace-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0111 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/operations-management/solution - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/operations-management/solution` module! - - A member of the @azure/avm-res-operationsmanagement-solution-module-owners-bicep or @azure/avm-res-operationsmanagement-solution-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0112 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/policy-insights/remediation - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/policy-insights/remediation` module! - - A member of the @azure/avm-res-policyinsights-remediation-module-owners-bicep or @azure/avm-res-policyinsights-remediation-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0113 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/power-bi-dedicated/capacity - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/power-bi-dedicated/capacity` module! - - A member of the @azure/avm-res-powerbidedicated-capacity-module-owners-bicep or @azure/avm-res-powerbidedicated-capacity-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0114 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/purview/account - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/purview/account` module! - - A member of the @azure/avm-res-purview-account-module-owners-bicep or @azure/avm-res-purview-account-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0115 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/recovery-services/vault - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/recovery-services/vault` module! - - A member of the @azure/avm-res-recoveryservices-vault-module-owners-bicep or @azure/avm-res-recoveryservices-vault-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0116 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/relay/namespace - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/relay/namespace` module! - - A member of the @azure/avm-res-relay-namespace-module-owners-bicep or @azure/avm-res-relay-namespace-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0117 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/resource-graph/query - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/resource-graph/query` module! - - A member of the @azure/avm-res-resourcegraph-query-module-owners-bicep or @azure/avm-res-resourcegraph-query-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0118 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/resources/deployment-script - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/resources/deployment-script` module! - - A member of the @azure/avm-res-resources-deploymentscript-module-owners-bicep or @azure/avm-res-resources-deploymentscript-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0119 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/resources/resource-group - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/resources/resource-group` module! - - A member of the @azure/avm-res-resources-resourcegroup-module-owners-bicep or @azure/avm-res-resources-resourcegroup-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0120 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/resources/tags - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/resources/tags` module! - - A member of the @azure/avm-res-resources-tags-module-owners-bicep or @azure/avm-res-resources-tags-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0121 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/search/search-service - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/search/search-service` module! - - A member of the @azure/avm-res-search-searchservice-module-owners-bicep or @azure/avm-res-search-searchservice-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0122 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/service-bus/namespace - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/service-bus/namespace` module! - - A member of the @azure/avm-res-servicebus-namespace-module-owners-bicep or @azure/avm-res-servicebus-namespace-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0123 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/service-fabric/cluster - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/service-fabric/cluster` module! - - A member of the @azure/avm-res-servicefabric-cluster-module-owners-bicep or @azure/avm-res-servicefabric-cluster-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0124 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/signal-r-service/signal-r - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/signal-r-service/signal-r` module! - - A member of the @azure/avm-res-signalrservice-signalr-module-owners-bicep or @azure/avm-res-signalrservice-signalr-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0125 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/signal-r-service/web-pub-sub - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/signal-r-service/web-pub-sub` module! - - A member of the @azure/avm-res-signalrservice-webpubsub-module-owners-bicep or @azure/avm-res-signalrservice-webpubsub-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0126 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/sql/managed-instance - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/sql/managed-instance` module! - - A member of the @azure/avm-res-sql-managedinstance-module-owners-bicep or @azure/avm-res-sql-managedinstance-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0127 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/sql/server - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/sql/server` module! - - A member of the @azure/avm-res-sql-server-module-owners-bicep or @azure/avm-res-sql-server-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0128 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/storage/storage-account - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/storage/storage-account` module! - - A member of the @azure/avm-res-storage-storageaccount-module-owners-bicep or @azure/avm-res-storage-storageaccount-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0129 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/synapse/private-link-hub - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/synapse/private-link-hub` module! - - A member of the @azure/avm-res-synapse-privatelinkhub-module-owners-bicep or @azure/avm-res-synapse-privatelinkhub-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0130 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/synapse/workspace - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/synapse/workspace` module! - - A member of the @azure/avm-res-synapse-workspace-module-owners-bicep or @azure/avm-res-synapse-workspace-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0131 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/virtual-machine-images/image-template - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/virtual-machine-images/image-template` module! - - A member of the @azure/avm-res-virtualmachineimages-imagetemplate-module-owners-bicep or @azure/avm-res-virtualmachineimages-imagetemplate-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0132 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/web/connection - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/web/connection` module! - - A member of the @azure/avm-res-web-connection-module-owners-bicep or @azure/avm-res-web-connection-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0133 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/web/hosting-environment - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/web/hosting-environment` module! - - A member of the @azure/avm-res-web-hostingenvironment-module-owners-bicep or @azure/avm-res-web-hostingenvironment-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0134 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/web/serverfarm - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/web/serverfarm` module! - - A member of the @azure/avm-res-web-serverfarm-module-owners-bicep or @azure/avm-res-web-serverfarm-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0135 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/web/site - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/web/site` module! - - A member of the @azure/avm-res-web-site-module-owners-bicep or @azure/avm-res-web-site-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0136 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/res/web/static-site - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/res/web/static-site` module! - - A member of the @azure/avm-res-web-staticsite-module-owners-bicep or @azure/avm-res-web-staticsite-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0137 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/ptn/avd-lza/insights - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/ptn/avd-lza/insights` module! - - A member of the @azure/avm-ptn-avd-lza-insights-module-owners-bicep or @azure/avm-ptn-avd-lza-insights-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0138 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/ptn/avd-lza/management-plane - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/ptn/avd-lza/management-plane` module! - - A member of the @azure/avm-ptn-avd-lza-managementplane-module-owners-bicep or @azure/avm-ptn-avd-lza-managementplane-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0139 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/ptn/avd-lza/networking - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/ptn/avd-lza/networking` module! - - A member of the @azure/avm-ptn-avd-lza-networking-module-owners-bicep or @azure/avm-ptn-avd-lza-networking-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0140 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/ptn/avd-lza/session-hosts - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/ptn/avd-lza/session-hosts` module! - - A member of the @azure/avm-ptn-avd-lza-sessionhosts-module-owners-bicep or @azure/avm-ptn-avd-lza-sessionhosts-module-contributors-bicep team will review it soon! - - - description: "AVM-MOD-0141 - Send automatic response to the issue author and mention the module owners and contributors team" - if: - - payloadType: Issues - - isAction: - action: Opened - - bodyContains: - pattern: | - avm/ptn/security/security-center - then: - - addLabel: - label: "Needs: Attention :wave:" - - addReply: - reply: | - @${issueAuthor}, thanks for submitting this issue for the `avm/ptn/security/security-center` module! - - A member of the @azure/avm-ptn-securitycenter-module-owners-bicep or @azure/avm-ptn-securitycenter-module-contributors-bicep team will review it soon! diff --git a/.github/policies/eventResponder.yml b/.github/policies/eventResponder.yml index 2fb6d23c9b..431a332691 100644 --- a/.github/policies/eventResponder.yml +++ b/.github/policies/eventResponder.yml @@ -17,6 +17,16 @@ configuration: then: - addLabel: label: "Needs: Triage :mag:" + - addReply: + reply: | + > [!IMPORTANT] + > **The "Needs: Triage :mag:" label must be removed once the triage process is complete !** + + > [!TIP] + > For additional guidance on how to triage this issue/PR, see the [BRM Issue Triage](https://azure.github.io/Azure-Verified-Modules/help-support/issue-triage/brm-issue-triage/) documentation. + + > [!NOTE] + > This label was added as per [ITA06](https://azure.github.io/Azure-Verified-Modules/help-support/issue-triage/issue-triage-automation/#ita06). - description: 'ITA08BCP - If "AVM" or "Azure Verified Modules" is mentioned in a new issue, add label of "Type: AVM :a: :v: :m:" on the issue' if: @@ -53,6 +63,10 @@ configuration: then: - addLabel: label: "Type: AVM :a: :v: :m:" + - addReply: + reply: | + > [!NOTE] + > The "Type: AVM :a: :v: :m:" label was added as per [ITA08BCP](https://azure.github.io/Azure-Verified-Modules/help-support/issue-triage/issue-triage-automation/#ita08bcp). - description: 'ITA09 - When #RR is used in an issue, add the "Needs: Author Feedback :ear:" label' if: @@ -64,6 +78,10 @@ configuration: then: - addLabel: label: "Needs: Author Feedback :ear:" + - addReply: + reply: | + > [!NOTE] + > The "Needs: Author Feedback :ear:" label was added as per [ITA09](https://azure.github.io/Azure-Verified-Modules/help-support/issue-triage/issue-triage-automation/#ita09). - description: 'ITA10 - When #wontfix is used in an issue, mark it by using the label of "Status: Won''t Fix :broken_heart:"' if: @@ -76,6 +94,10 @@ configuration: - addLabel: label: "Status: Won't Fix :broken_heart:" - closeIssue + - addReply: + reply: | + > [!NOTE] + > The "Status: Won't Fix :broken_heart:" label was added and the issue was closed as per [ITA10](https://azure.github.io/Azure-Verified-Modules/help-support/issue-triage/issue-triage-automation/#ita10). - description: 'ITA11 - When a reply from anyone to an issue occurs, remove the "Needs: Author Feedback :ear:" label and label with "Needs: Attention :wave:"' if: @@ -92,6 +114,10 @@ configuration: label: "Needs: Author Feedback :ear:" - addLabel: label: "Needs: Attention :wave:" + - addReply: + reply: | + > [!NOTE] + > The "Needs: Author Feedback :ear:" label was removed and the "Needs: Attention :wave:" label was added as per [ITA11](https://azure.github.io/Azure-Verified-Modules/help-support/issue-triage/issue-triage-automation/#ita11). - description: "ITA12 - Clean email replies on every comment" if: @@ -99,7 +125,7 @@ configuration: then: - cleanEmailReply - - description: 'ITA15 - remove the "Needs: Triage" label from a PR, if it already has a "Type: XYZ" label assigned at the time of creating it.' + - description: 'ITA15 - remove the "Needs: Triage" label from a PR, if it already has a "Type: XYZ" label added at the time of creating it.' if: - payloadType: Pull_Request - or: @@ -126,6 +152,10 @@ configuration: then: - removeLabel: label: "Needs: Triage :mag:" + - addReply: + reply: | + > [!NOTE] + > The "Needs: Triage :mag:" label was removed as per [ITA15](https://azure.github.io/Azure-Verified-Modules/help-support/issue-triage/issue-triage-automation/#ita15). - description: 'ITA16 - Add the "Status: Owners Identified :metal:" label when someone is assigned to a Module Proposal' if: @@ -139,6 +169,11 @@ configuration: then: - addLabel: label: "Status: Owners Identified :metal:" + - addReply: + reply: | + > [!NOTE] + > The "Status: Owners Identified :metal:" label was added as per [ITA15](https://azure.github.io/Azure-Verified-Modules/help-support/issue-triage/issue-triage-automation/#ita15). + triggerOnOwnActions: true - description: 'ITA20 - If the type is feature request, assign the "Type: Feature Request :heavy_plus_sign:" label on the issue' if: @@ -153,6 +188,10 @@ configuration: then: - addLabel: label: "Type: Feature Request :heavy_plus_sign:" + - addReply: + reply: | + > [!NOTE] + > The "Type: Feature Request :heavy_plus_sign:" label was added as per [ITA20](https://azure.github.io/Azure-Verified-Modules/help-support/issue-triage/issue-triage-automation/#ita20). - description: 'ITA21 - If the type is bug, assign the "Type: Bug :bug:" label on the issue' if: @@ -167,6 +206,10 @@ configuration: then: - addLabel: label: "Type: Bug :bug:" + - addReply: + reply: | + > [!NOTE] + > The "Type: Bug :bug:" label was added as per [ITA21](https://azure.github.io/Azure-Verified-Modules/help-support/issue-triage/issue-triage-automation/#ita21). - description: 'ITA22 - If the type is security bug, assign the "Type: Security Bug :lock:" label on the issue' if: @@ -181,3 +224,7 @@ configuration: then: - addLabel: label: "Type: Security Bug :lock:" + - addReply: + reply: | + > [!NOTE] + > The "Type: Security Bug :lock:" label was added as per [ITA22](https://azure.github.io/Azure-Verified-Modules/help-support/issue-triage/issue-triage-automation/#ita22). diff --git a/.github/policies/scheduledSearches.yml b/.github/policies/scheduledSearches.yml index 01fd577741..28d5288ef5 100644 --- a/.github/policies/scheduledSearches.yml +++ b/.github/policies/scheduledSearches.yml @@ -7,7 +7,7 @@ disabled: false configuration: resourceManagementConfiguration: scheduledSearches: - - description: ITA01BCP.1 - Label and assign AVM issues that have been marked as requiring triage and have not had any activity for 3 business days. + - description: "ITA01BCP.1 - Label and comment AVM issues that have been marked as requiring triage and have not had any activity for 3 business days." frequencies: - weekday: day: Monday @@ -31,13 +31,20 @@ configuration: - mentionUsers: mentionees: - Azure/avm-core-team-technical-bicep - replyTemplate: "Tagging the AVM Core Team (${mentionees}) due to a module owner or contributor having not responded to this issue within 3 business days. The AVM Core Team will attempt to contact the module owners/contributors directly." + replyTemplate: | + > [!WARNING] + > **Tagging the AVM Core Team (${mentionees}) due to a module owner or contributor having not responded to this issue within 3 business days. The AVM Core Team will attempt to contact the module owners/contributors directly.** + + > [!TIP] + > - To prevent further actions to take effect, the "Status: Response Overdue 🚩" label must be removed, once this issue has been responded to. + > - To avoid this rule being (re)triggered, the ""Needs: Triage :mag:" label must be removed as part of the triage process (when the issue is first responded to)! + + > [!NOTE] + > This message was posted as per [ITA01BCP](https://azure.github.io/Azure-Verified-Modules/help-support/issue-triage/issue-triage-automation/#ita01bcp1-2). - addLabel: label: "Status: Response Overdue :triangular_flag_on_post:" - - assignTo: - user: Azure/avm-core-team-technical-bicep - - description: ITA01BCP.2 - Label and assign AVM issues that have been marked as requiring triage and have not had any activity for 3 business days. + - description: "ITA01BCP.2 - Label and comment AVM issues that have been marked as requiring triage and have not had any activity for 3 business days." frequencies: - weekday: day: Thursday @@ -58,13 +65,20 @@ configuration: - mentionUsers: mentionees: - Azure/avm-core-team-technical-bicep - replyTemplate: "Tagging the AVM Core Team (${mentionees}) due to a module owner or contributor having not responded to this issue within 3 business days. The AVM Core Team will attempt to contact the module owners/contributors directly." + replyTemplate: | + > [!WARNING] + > **Tagging the AVM Core Team (${mentionees}) due to a module owner or contributor having not responded to this issue within 3 business days. The AVM Core Team will attempt to contact the module owners/contributors directly.** + + > [!TIP] + > - To prevent further actions to take effect, the "Status: Response Overdue 🚩" label must be removed, once this issue has been responded to. + > - To avoid this rule being (re)triggered, the ""Needs: Triage :mag:" label must be removed as part of the triage process (when the issue is first responded to)! + + > [!NOTE] + > This message was posted as per [ITA01BCP](https://azure.github.io/Azure-Verified-Modules/help-support/issue-triage/issue-triage-automation/#ita01bcp1-2). - addLabel: label: "Status: Response Overdue :triangular_flag_on_post:" - - assignTo: - user: Azure/avm-core-team-technical-bicep - - description: ITA02BCP.1 - Label issues as Needs Immediate Attention and leave comment if after an additional 3 business days there's still no update to the issue. + - description: "ITA02BCP.1 - Label and comment issues as Needs Immediate Attention and leave comment if after an additional 3 business days there's still no update to the issue." frequencies: - weekday: day: Monday @@ -88,11 +102,20 @@ configuration: - mentionUsers: mentionees: - Azure/avm-core-team-technical-bicep - replyTemplate: "This issue requires the AVM Core Team's (${mentionees}) immediate attention as it hasn't been responded to within 6 business days." + replyTemplate: | + > [!CAUTION] + > **This issue requires the AVM Core Team's (${mentionees}) immediate attention as it hasn't been responded to within 6 business days. ** + + > [!TIP] + > - To avoid this rule being (re)triggered, the "Needs: Triage :mag:" and "Status: Response Overdue :triangular_flag_on_post:" labels must be removed when the issue is first responded to! + > - Remove the "Needs: Immediate Attention :bangbang:" label once the issue has been responded to. + + > [!NOTE] + > This message was posted as per [ITA02BCP](https://azure.github.io/Azure-Verified-Modules/help-support/issue-triage/issue-triage-automation/#ita02bcp1-2). - addLabel: label: "Needs: Immediate Attention :bangbang:" - - description: ITA02BCP.2 - Label issues as Needs Immediate Attention and leave comment if after an additional 3 business days there's still no update to the issue. + - description: "ITA02BCP.2 - Label and comment issues as Needs Immediate Attention and leave comment if after an additional 3 business days there's still no update to the issue." frequencies: - weekday: day: Thursday @@ -113,11 +136,20 @@ configuration: - mentionUsers: mentionees: - Azure/avm-core-team-technical-bicep - replyTemplate: "This issue requires the AVM Core Team's (${mentionees}) immediate attention as it hasn't been responded to within 6 business days." + replyTemplate: | + > [!CAUTION] + > **This issue requires the AVM Core Team's (${mentionees}) immediate attention as it hasn't been responded to within 6 business days. ** + + > [!TIP] + > - To avoid this rule being (re)triggered, the "Needs: Triage :mag:" and "Status: Response Overdue :triangular_flag_on_post:" labels must be removed when the issue is first responded to! + > - Remove the "Needs: Immediate Attention :bangbang:" label once the issue has been responded to. + + > [!NOTE] + > This message was posted as per [ITA02BCP](https://azure.github.io/Azure-Verified-Modules/help-support/issue-triage/issue-triage-automation/#ita02bcp1-2). - addLabel: label: "Needs: Immediate Attention :bangbang:" - - description: ITA03BCP - Label and assign Bicep PG to security issues that have not had any activity for 5 business days. + - description: "ITA03BCP - Label and mention Bicep PG to security issues that have not had any activity for 5 business days." frequencies: - weekday: day: Monday @@ -151,13 +183,20 @@ configuration: - mentionUsers: mentionees: - Azure/bicep-admins - replyTemplate: "Tagging the Bicep PG team (${mentionees}) due to a module owner or contributor having not responded to this issue within 3 business days. The AVM Core Team will attempt to contact the module owners/contributors directly." + replyTemplate: | + > [!CAUTION] + > **Tagging the Bicep PG team (${mentionees}) due to a module owner or contributor having not responded to this issue within 3 business days. The AVM Core Team will attempt to contact the module owners/contributors directly.** + + > [!TIP] + > - To avoid this rule being (re)triggered, the "Needs: Triage :mag:" and "Status: Response Overdue :triangular_flag_on_post:" labels must be removed when the issue is first responded to! + > - Remove the "Needs: Immediate Attention :bangbang:" label once the issue has been responded to. + + > [!NOTE] + > This message was posted as per [ITA03BCP](https://azure.github.io/Azure-Verified-Modules/help-support/issue-triage/issue-triage-automation/#ita03bcp). - addLabel: label: "Needs: Immediate Attention :bangbang:" - - assignTo: - user: Azure/bicep-admins - - description: ITA04 - Label issues that have been marked as requiring author feedback but have not had any activity for 4 days. + - description: "ITA04 - Label issues that have been marked as requiring author feedback but have not had any activity for 4 days." frequencies: - hourly: hour: 3 @@ -175,9 +214,19 @@ configuration: label: "Status: No Recent Activity :zzz:" - addReply: reply: | - @${issueAuthor}, this issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for **4 days**. It will be closed if no further activity occurs **within 3 days of this comment**. + > [!IMPORTANT] + > @${issueAuthor}, this issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for **4 days**. It will be closed if no further activity occurs **within 3 days of this comment**. - - description: ITA05 - Close issues that have been marked as requiring author feedback but have not had any activity for 3 days. + > [!TIP] + > To prevent further actions to take effect, one of the following conditions must be met: + > - The author must respond in a comment within 3 days of this comment. + > - The "Status: No Recent Activity :zzz:" label must be removed. + > - If applicable, the "Status: Long Term :hourglass_flowing_sand:" or the "Needs: Module Owner :mega:" label must be added. + + > [!NOTE] + > This message was posted as per [ITA04](https://azure.github.io/Azure-Verified-Modules/help-support/issue-triage/issue-triage-automation/#ita04). + + - description: 'ITA05A - Close issues that have been marked as requiring author feedback but have not had any activity for 3 days, unless it''s been marked with the "Status long term" label.' frequencies: - hourly: hour: 3 @@ -188,8 +237,6 @@ configuration: label: "Needs: Author Feedback :ear:" - hasLabel: label: "Status: No Recent Activity :zzz:" - - isNotLabeledWith: - label: "Status: Long Term :hourglass_flowing_sand:" - isNotLabeledWith: label: "Needs: Module Owner :mega:" - noActivitySince: @@ -197,5 +244,40 @@ configuration: actions: - addReply: reply: | - @${issueAuthor}, this issue will now be closed, as it has been marked as requiring author feedback but has not had any activity for **7 days**. + > [!WARNING] + > @${issueAuthor}, this issue will now be closed, as it has been marked as requiring author feedback but has not had any activity for **7 days**. + + > [!TIP] + > In case this issue needs to be reopened (e.g., the author responds after the issue was closed), the "Status: No Recent Activity :zzz:" label must be removed. + + > [!NOTE] + > This message was posted as per [ITA05](https://azure.github.io/Azure-Verified-Modules/help-support/issue-triage/issue-triage-automation/#ita05). + - closeIssue + + - description: 'ITA05B - Close issues that have been marked as requiring author feedback but have not had any activity for 3 days, unless it''s been marked with the "Status long term" label.' + frequencies: + - hourly: + hour: 3 + filters: + - isIssue + - isOpen + - hasLabel: + label: "Needs: Author Feedback :ear:" + - hasLabel: + label: "Status: No Recent Activity :zzz:" + - isNotLabeledWith: + label: "Status: Long Term :hourglass_flowing_sand:" + - noActivitySince: + days: 3 + actions: + - addReply: + reply: | + > [!WARNING] + > @${issueAuthor}, this issue will now be closed, as it has been marked as requiring author feedback but has not had any activity for **7 days**. + + > [!TIP] + > In case this issue needs to be reopened (e.g., the author responds after the issue was closed), the "Status: No Recent Activity :zzz:" label must be removed. + + > [!NOTE] + > This message was posted as per [ITA05](https://azure.github.io/Azure-Verified-Modules/help-support/issue-triage/issue-triage-automation/#ita05). - closeIssue From 45b846ef8784d9c135a19be795227c6b3c2fcc98 Mon Sep 17 00:00:00 2001 From: Erika Gressi <56914614+eriqua@users.noreply.github.com> Date: Mon, 25 Mar 2024 12:07:00 +0000 Subject: [PATCH 59/73] feat: PSRule them all (#1392) ## Description - Add a platform workflow to run PSRule analisys on the whole library, manually and on weekly schedule > Example for Reliability check > ![image](https://github.com/Azure/bicep-registry-modules/assets/56914614/31300522-7eba-4a4f-8760-2e85ef3dfa0e) - Allow selecting specific WAF pillar in input (defaults to Azure.Default = all pillars) > ![image](https://github.com/Azure/bicep-registry-modules/assets/56914614/6462cff7-3be8-492d-bd98-04c5a9f5bf27) > ![image](https://github.com/Azure/bicep-registry-modules/assets/56914614/8fd5f41a-ed5a-4fa9-863f-bb9dd4fbfd03) - Fix bug with filtering unique values when listing rules in the job summary ## Pipeline Reference | Pipeline | | -------- | | [![avm.platform.check.psrule](https://github.com/eriqua/bicep-registry-modules/actions/workflows/avm.platform.check.psrule.yml/badge.svg)](https://github.com/eriqua/bicep-registry-modules/actions/workflows/avm.platform.check.psrule.yml) (test new workflow)| | [![avm.res.app-configuration.configuration-store](https://github.com/eriqua/bicep-registry-modules/actions/workflows/avm.res.app-configuration.configuration-store.yml/badge.svg?branch=feat%2Fpsrule-them-all)](https://github.com/eriqua/bicep-registry-modules/actions/workflows/avm.res.app-configuration.configuration-store.yml) (test usual module validation workflow) | ## Type of Change - [x] Update to CI Environment or utlities (Non-module effecting changes) - [ ] Azure Verified Module updates: - [ ] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [ ] I have run `Set-AVMModule` locally to generate the supporting module files. - [ ] My corresponding pipelines / checks run clean and green without any errors or warnings --- .../avm-validateModulePSRule/action.yml | 24 +-- .../workflows/avm.platform.check.psrule.yml | 199 ++++++++++++++++++ .../psrule/Set-PSRuleGitHubOutput.ps1 | 10 +- .../staticValidation/psrule/ps-rule.yaml | 5 +- 4 files changed, 213 insertions(+), 25 deletions(-) create mode 100644 .github/workflows/avm.platform.check.psrule.yml diff --git a/.github/actions/templates/avm-validateModulePSRule/action.yml b/.github/actions/templates/avm-validateModulePSRule/action.yml index 6cc60d4b67..2ac26ee60a 100644 --- a/.github/actions/templates/avm-validateModulePSRule/action.yml +++ b/.github/actions/templates/avm-validateModulePSRule/action.yml @@ -5,20 +5,6 @@ ## This composite action contains the logic to validate a module using a set of PSRule tests ## ######################################################### -## -##-------------------------------------------## -## ACTION PARAMETERS ## -##-------------------------------------------## -## -## |=================================================================================================================================================================| -## | Parameter | Required | Default | Description | Example | -## |--------------------------|----------|---------|--------------------------------------|--------------------------------------------------------------------------| -## | templateFilePath | true | '' | The path to the module PSRule tests. | 'modules/api-management/service/.test/common/main.test.bicep' | -## | subscriptionId | false | '' | The subscriptionId to deploy to | '1a97b80a-4dda-4f50-ab53-349e29344654' | -## | managementGroupId | false | '' | The managementGroupId to deploy to | '1a97b80a-4dda-4f50-ab53-349e29344654' | -## |=================================================================================================================================================================| -## -##---------------------------------------------## name: "Execute PSRule module tests" description: "Execute PSRule module tests (if any)" @@ -37,6 +23,10 @@ inputs: psrulePath: description: "The path to PSRule configurations" required: false + skipPassedRulesReport: + description: "Show only failed rules in job summary" + required: false + default: $false psruleBaseline: description: "The PSRule baseline to be used" required: true @@ -155,9 +145,9 @@ runs: # Populate parameter input $ParameterInput = @{ - inputFilePath = '${{ inputs.templateFilePath}}-PSRule-output.csv' - outputFilePath = '${{ inputs.templateFilePath}}-PSRule-output.md' - skipPassedRulesReport = $false + inputFilePath = '${{ inputs.templateFilePath}}-PSRule-output.csv' + outputFilePath = '${{ inputs.templateFilePath}}-PSRule-output.md' + skipPassedRulesReport = ${{ inputs.skipPassedRulesReport}} } Write-Verbose ('Set PS Rule Output with following parameters:`n{0}' -f (ConvertTo-Json $ParameterInput -Depth 10)) -Verbose diff --git a/.github/workflows/avm.platform.check.psrule.yml b/.github/workflows/avm.platform.check.psrule.yml new file mode 100644 index 0000000000..fd7a7d9308 --- /dev/null +++ b/.github/workflows/avm.platform.check.psrule.yml @@ -0,0 +1,199 @@ +name: "avm.platform.check.psrule" + +on: + workflow_dispatch: + inputs: + psruleBaseline: + type: choice + description: "PSRule baseline" + required: true + default: "Azure.Default" + options: + - Azure.Default + - Azure.Pillar.CostOptimization + - Azure.Pillar.OperationalExcellence + - Azure.Pillar.PerformanceEfficiency + - Azure.Pillar.Reliability + - Azure.Pillar.Security + skipPassedRulesReport: + type: boolean + description: "Show only failed rules in job summary" + required: true + default: true + schedule: + - cron: "0 12 * * 0" # Weekly Sunday Analysis + +env: + workflowPath: ".github/workflows/avm.platform.check.psrule.yml" + targetPath: "avm/res/" + PSRuleOutputFilePath: "avm/res/PSRule-output.csv" + PSRuleInputFilePath: "avm/res/PSRule-output.md" + psRuleFilterRegex: "(defaults|waf-aligned)" # The regex used to filter PSRule compliant files + psrulePath: "avm/utilities/pipelines/staticValidation/psrule" + ARM_SUBSCRIPTION_ID: "${{ secrets.ARM_SUBSCRIPTION_ID }}" + ARM_MGMTGROUP_ID: "${{ secrets.ARM_MGMTGROUP_ID }}" + TOKEN_NAMEPREFIX: "${{ secrets.TOKEN_NAMEPREFIX }}" + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_init_psrule_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}}" + outputs: + workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }} + + ############## + # PSRule # + ############## + job_psrule: + runs-on: ubuntu-latest + name: "PSRule validation" + needs: + - job_init_psrule_pipeline + steps: + # [Init] task(s) + # --------------------------- + - name: Checkout + uses: actions/checkout@v4 + + - name: Set environment + uses: ./.github/actions/templates/avm-setEnvironment + + # [Token replacement] task(s) + # --------------------------- + - name: Replace tokens in relevant files + uses: azure/powershell@v1 + with: + azPSVersion: "latest" + inlineScript: | + # Grouping task logs + Write-Output '::group::Replace tokens in relevant files' + + # Load used functions + . (Join-Path $env:GITHUB_WORKSPACE 'avm' 'utilities' 'pipelines' 'sharedScripts' 'tokenReplacement' 'Convert-TokensInFileList.ps1') + . (Join-Path $env:GITHUB_WORKSPACE 'avm' 'utilities' 'pipelines' 'sharedScripts' 'Get-LocallyReferencedFileList.ps1') + + $targetPath = Join-Path $env:GITHUB_WORKSPACE '${{ env.targetPath }}' + $psRuleFilterRegex = '${{ env.psRuleFilterRegex }}' + + Write-Verbose ('targetPath [{0}]' -f $targetPath) -Verbose + + # Get target files in target path + $targetFileList = @() + # Retrieve all relevant test files in targetPath + $allTestFiles = (Get-ChildItem -Path $targetPath -Recurse -Filter 'main.test.bicep').FullName | Sort-Object + $relevantTestFiles = $allTestFiles | Where-Object { $_ -match $psRuleFilterRegex } + # Add all relevant test files and related module template files as they may contain tokens + foreach ($relevantTestFile in $relevantTestFiles) { + $targetFileList += $relevantTestFile + $targetFileList += (Get-LocallyReferencedFileList -FilePath $relevantTestFile) + } + + $targetFileList = $targetFileList | Sort-Object -Unique + + # Construct Token Function Input + $ConvertTokensInputs = @{ + FilePathList = $targetFileList + Tokens = @{} + } + + # Add enforced tokens + $ConvertTokensInputs.Tokens += @{ + subscriptionId = '${{ env.ARM_SUBSCRIPTION_ID }}' + managementGroupId = '${{ env.ARM_MGMTGROUP_ID }}' + } + + # Add local (source control) tokens + $tokenMap = @{} + foreach ($token in (Get-ChildItem env: | Where-Object -Property Name -Like "localToken_*")) { + $tokenMap += @{ $token.Name.Replace('localToken_','','OrdinalIgnoreCase') = $token.value } + } + Write-Verbose ('Using local tokens [{0}]' -f ($tokenMap.Keys -join ', ')) -Verbose + $ConvertTokensInputs.Tokens += $tokenMap + + # Swap 'namePrefix' token if empty and provided as a GitHub secret + if([String]::IsNullOrEmpty($ConvertTokensInputs.Tokens['namePrefix'])){ + Write-Verbose 'Using [namePrefix] token from GitHub' -Verbose + $ConvertTokensInputs.Tokens['namePrefix'] = '${{ env.TOKEN_NAMEPREFIX }}' + } + + Write-Verbose "Convert Tokens Input:`n $($ConvertTokensInputs | ConvertTo-Json -Depth 10)" -Verbose + + # Invoke Token Replacement Functionality [For Module] + $null = Convert-TokensInFileList @ConvertTokensInputs + + Write-Output '::endgroup::' + + # [PSRule validation] task(s) + #----------------------------- + - name: Run PSRule analysis + uses: microsoft/ps-rule@v2.9.0 + with: + modules: "PSRule.Rules.Azure" + prerelease: true + baseline: "${{(fromJson(needs.job_init_psrule_pipeline.outputs.workflowInput)).psruleBaseline }}" + inputPath: "${{(fromJson(needs.job_init_psrule_pipeline.outputs.workflowInput)).targetPath }}" + outputFormat: Csv + outputPath: "${{ env.PSRuleOutputFilePath }}" + option: "${{ github.workspace }}/${{ env.psrulePath}}/ps-rule.yaml" # Path to PSRule configuration options file + source: "${{ env.psrulePath}}/.ps-rule/" # Path to folder containing suppression rules to use for analysis. + summary: false # Disabling as taken care in customized task + + # [Print to Summary] task(s) + #----------------------------- + - name: Parse CSV content + if: always() + uses: azure/powershell@v1 + with: + azPSVersion: "latest" + inlineScript: | + # Grouping task logs + Write-Output '::group::Parse CSV content' + + # Load used functions + . (Join-Path $env:GITHUB_WORKSPACE 'avm' 'utilities' 'pipelines' 'staticValidation' 'psrule' 'Set-PSRuleGitHubOutput.ps1') + + # Populate parameter input + $ParameterInput = @{ + inputFilePath = '${{ env.PSRuleOutputFilePath }}' + outputFilePath = '${{ env.PSRuleInputFilePath }}' + skipPassedRulesReport = [System.Convert]::ToBoolean('${{(fromJson(needs.job_init_psrule_pipeline.outputs.workflowInput)).skipPassedRulesReport }}') + } + + Write-Verbose ('Set PS Rule Output with following parameters:`n{0}' -f (ConvertTo-Json $ParameterInput -Depth 10)) -Verbose + + # Invoke Set PSRule Output Functionality + $null = Set-PSRuleGitHubOutput @ParameterInput + + Write-Output '::endgroup::' + + - name: Output to GitHub job summaries + if: always() + shell: pwsh + run: | + # Grouping task logs + Write-Output '::group::Output to GitHub job summaries' + + $mdPSRuleOutputFilePath = Join-Path $env:GITHUB_WORKSPACE '${{ env.PSRuleInputFilePath }}' + + if (-not (Test-Path $mdPSRuleOutputFilePath)) { + Write-Warning ('Input file [{0}] not found. Please check if the previous task threw an error and try again.' -f $mdPSRuleOutputFilePath) + return '' + } else { + Get-Content $mdPSRuleOutputFilePath >> $env:GITHUB_STEP_SUMMARY + Write-Verbose ('Successfully printed out file [{0}] to Job Summaries' -f $mdPSRuleOutputFilePath) -Verbose + } + + Write-Output '::endgroup::' diff --git a/avm/utilities/pipelines/staticValidation/psrule/Set-PSRuleGitHubOutput.ps1 b/avm/utilities/pipelines/staticValidation/psrule/Set-PSRuleGitHubOutput.ps1 index 72e8b796e1..f48a92bdb5 100644 --- a/avm/utilities/pipelines/staticValidation/psrule/Set-PSRuleGitHubOutput.ps1 +++ b/avm/utilities/pipelines/staticValidation/psrule/Set-PSRuleGitHubOutput.ps1 @@ -45,11 +45,9 @@ function Set-PSRuleGitHubOutput { Write-Warning ('Input File [{0}] not found' -f $inputFilePath) return '' } else { - $results = Import-Csv -Path $inputFilePath - - $passedRules += $results | Where-Object { $_.Outcome -EQ 'Pass' } | Sort-Object -Property 'RuleName' -Unique - $failedRules += $results | Where-Object { $_.Outcome -EQ 'Fail' } | Sort-Object -Property 'RuleName' -Unique + $passedRules += $results | Where-Object { $_.Outcome -EQ 'Pass' } | Sort-Object -Property 'TargetName','RuleName' -Unique + $failedRules += $results | Where-Object { $_.Outcome -EQ 'Fail' } | Sort-Object -Property 'TargetName','RuleName' -Unique ###################### # Set output content # @@ -92,7 +90,7 @@ function Set-PSRuleGitHubOutput { foreach ($content in $failedRules ) { # Shorten the target name for deployment resoure type if ($content.TargetType -eq 'Microsoft.Resources/deployments') { - $content.TargetName = $content.TargetName.replace('/home/runner/work/ResourceModules/ResourceModules/modules/', '') + $content.TargetName = $content.TargetName.replace('/home/runner/work/bicep-registry-modules/bicep-registry-modules/avm/', '') } # Build hyperlinks to PSRule documentation for the rules @@ -131,7 +129,7 @@ function Set-PSRuleGitHubOutput { foreach ($content in $passedRules ) { # Shorten the target name for deployment resoure type if ($content.TargetType -eq 'Microsoft.Resources/deployments') { - $content.TargetName = $content.TargetName.replace('/home/runner/work/ResourceModules/ResourceModules/modules/', '') + $content.TargetName = $content.TargetName.replace('/home/runner/work/bicep-registry-modules/bicep-registry-modules/avm/', '') } # Build hyperlinks to PSRule documentation for the rules diff --git a/avm/utilities/pipelines/staticValidation/psrule/ps-rule.yaml b/avm/utilities/pipelines/staticValidation/psrule/ps-rule.yaml index d6ced73afb..f5bc660b72 100644 --- a/avm/utilities/pipelines/staticValidation/psrule/ps-rule.yaml +++ b/avm/utilities/pipelines/staticValidation/psrule/ps-rule.yaml @@ -35,8 +35,9 @@ input: pathIgnore: # Exclude all files. - "*" - # Only process test files. - - "!avm/**/*.test.bicep" + # Only process defaults and waf-aligned test files. + - "!avm/**/defaults/*.test.bicep" + - "!avm/**/waf-aligned/*.test.bicep" configuration: # Enable automatic expansion of Azure parameter files. From 05312ec3732195a8d5d4344fd98677bc23f8ad85 Mon Sep 17 00:00:00 2001 From: Alexander Sehr Date: Mon, 25 Mar 2024 16:27:18 +0100 Subject: [PATCH 60/73] fix: Corrected MSI handling for DigitalTwin module (#1400) ## Description - Corrected MSI handling for DigitalTwin module - ServiceBus & EventHub endpoints only support either SystemAssigned or a single UserAssigned identity ![image](https://github.com/Azure/bicep-registry-modules/assets/5365358/bb96d142-b54a-459e-becb-e037a9c56bf9) - The system assigned identity does not return the principal ID ![image](https://github.com/Azure/bicep-registry-modules/assets/5365358/b7cd8de8-4bec-45bc-bb4d-34d408b5f2ad) - Changed deployment of endpoints to an array as per what is technically supported ![image](https://github.com/Azure/bicep-registry-modules/assets/5365358/a1cd167a-1ef6-48f3-b1da-efe126cfc2bf) - Removed `uniqueString` function from test cases as it caused issues and shortened `serviceShort` ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.digital-twins.digital-twins-instance](https://github.com/AlexanderSehr/bicep-registry-modules/actions/workflows/avm.res.digital-twins.digital-twins-instance.yml/badge.svg?branch=users%2Falsehr%2FdiagTwinFix&event=workflow_dispatch)](https://github.com/AlexanderSehr/bicep-registry-modules/actions/workflows/avm.res.digital-twins.digital-twins-instance.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [ ] Azure Verified Module updates: - [x] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [x] Breaking changes and I have bumped the MAJOR version in `version.json`. - [x] Update to documentation --------- Co-authored-by: Erika Gressi <56914614+eriqua@users.noreply.github.com> --- .../digital-twins-instance/README.md | 147 +++++++++++------- .../endpoint--event-hub/README.md | 12 +- .../endpoint--event-hub/main.bicep | 13 +- .../endpoint--event-hub/main.json | 16 +- .../endpoint--service-bus/README.md | 12 +- .../endpoint--service-bus/main.bicep | 13 +- .../endpoint--service-bus/main.json | 16 +- .../digital-twins-instance/main.bicep | 24 +-- .../digital-twins-instance/main.json | 125 +++++++-------- .../tests/e2e/defaults/main.test.bicep | 2 +- .../tests/e2e/max/main.test.bicep | 71 +++++---- .../tests/e2e/pe/main.test.bicep | 2 +- .../tests/e2e/waf-aligned/main.test.bicep | 6 +- 13 files changed, 247 insertions(+), 212 deletions(-) diff --git a/avm/res/digital-twins/digital-twins-instance/README.md b/avm/res/digital-twins/digital-twins-instance/README.md index ecd905bd7f..81bab0a922 100644 --- a/avm/res/digital-twins/digital-twins-instance/README.md +++ b/avm/res/digital-twins/digital-twins-instance/README.md @@ -49,7 +49,7 @@ This instance deploys the module with the minimum set of required parameters. module digitalTwinsInstance 'br/public:avm/res/digital-twins/digital-twins-instance:' = { name: 'digitalTwinsInstanceDeployment' params: { - name: 'dtdtimin001' + name: 'dtdimin001' } } ``` @@ -67,7 +67,7 @@ module digitalTwinsInstance 'br/public:avm/res/digital-twins/digital-twins-insta "contentVersion": "1.0.0.0", "parameters": { "name": { - "value": "dtdtimin001" + "value": "dtdimin001" } } } @@ -90,7 +90,7 @@ module digitalTwinsInstance 'br/public:avm/res/digital-twins/digital-twins-insta name: 'digitalTwinsInstanceDeployment' params: { // Required parameters - name: 'dtdtimax001' + name: 'dtdmax001' // Non-required parameters diagnosticSettings: [ { @@ -106,18 +106,22 @@ module digitalTwinsInstance 'br/public:avm/res/digital-twins/digital-twins-insta workspaceResourceId: '' } ] - eventGridEndpoint: { - eventGridDomainId: '' - topicEndpoint: '' - } - eventHubEndpoint: { - authenticationType: 'IdentityBased' - endpointUri: '' - entityPath: '' - managedIdentities: { - userAssignedResourceId: '' + eventGridEndpoints: [ + { + eventGridDomainId: '' + topicEndpoint: '' } - } + ] + eventHubEndpoints: [ + { + authenticationType: 'IdentityBased' + endpointUri: '' + entityPath: '' + managedIdentities: { + userAssignedResourceId: '' + } + } + ] location: '' lock: { kind: 'CanNotDelete' @@ -154,14 +158,26 @@ module digitalTwinsInstance 'br/public:avm/res/digital-twins/digital-twins-insta roleDefinitionIdOrName: '' } ] - serviceBusEndpoint: { - authenticationType: 'IdentityBased' - endpointUri: '' - entityPath: '' - managedIdentities: { - userAssignedResourceId: '' + serviceBusEndpoints: [ + { + authenticationType: 'IdentityBased' + endpointUri: '' + entityPath: '' + managedIdentities: { + userAssignedResourceId: '' + } + name: 'ServiceBusPrimary' } - } + { + authenticationType: 'IdentityBased' + endpointUri: '' + entityPath: '' + managedIdentities: { + systemAssigned: true + } + name: 'ServiceBusSeconday' + } + ] tags: { Environment: 'Non-Prod' 'hidden-title': 'This is visible in the resource name' @@ -185,7 +201,7 @@ module digitalTwinsInstance 'br/public:avm/res/digital-twins/digital-twins-insta "parameters": { // Required parameters "name": { - "value": "dtdtimax001" + "value": "dtdmax001" }, // Non-required parameters "diagnosticSettings": { @@ -204,21 +220,25 @@ module digitalTwinsInstance 'br/public:avm/res/digital-twins/digital-twins-insta } ] }, - "eventGridEndpoint": { - "value": { - "eventGridDomainId": "", - "topicEndpoint": "" - } + "eventGridEndpoints": { + "value": [ + { + "eventGridDomainId": "", + "topicEndpoint": "" + } + ] }, - "eventHubEndpoint": { - "value": { - "authenticationType": "IdentityBased", - "endpointUri": "", - "entityPath": "", - "managedIdentities": { - "userAssignedResourceId": "" + "eventHubEndpoints": { + "value": [ + { + "authenticationType": "IdentityBased", + "endpointUri": "", + "entityPath": "", + "managedIdentities": { + "userAssignedResourceId": "" + } } - } + ] }, "location": { "value": "" @@ -266,15 +286,27 @@ module digitalTwinsInstance 'br/public:avm/res/digital-twins/digital-twins-insta } ] }, - "serviceBusEndpoint": { - "value": { - "authenticationType": "IdentityBased", - "endpointUri": "", - "entityPath": "", - "managedIdentities": { - "userAssignedResourceId": "" + "serviceBusEndpoints": { + "value": [ + { + "authenticationType": "IdentityBased", + "endpointUri": "", + "entityPath": "", + "managedIdentities": { + "userAssignedResourceId": "" + }, + "name": "ServiceBusPrimary" + }, + { + "authenticationType": "IdentityBased", + "endpointUri": "", + "entityPath": "", + "managedIdentities": { + "systemAssigned": true + }, + "name": "ServiceBusSeconday" } - } + ] }, "tags": { "value": { @@ -304,7 +336,7 @@ module digitalTwinsInstance 'br/public:avm/res/digital-twins/digital-twins-insta name: 'digitalTwinsInstanceDeployment' params: { // Required parameters - name: 'dtdtipep001' + name: 'dtdpep001' // Non-required parameters location: '' privateEndpoints: [ @@ -339,7 +371,7 @@ module digitalTwinsInstance 'br/public:avm/res/digital-twins/digital-twins-insta "parameters": { // Required parameters "name": { - "value": "dtdtipep001" + "value": "dtdpep001" }, // Non-required parameters "location": { @@ -382,7 +414,7 @@ module digitalTwinsInstance 'br/public:avm/res/digital-twins/digital-twins-insta name: 'digitalTwinsInstanceDeployment' params: { // Required parameters - name: 'dtdtiwaf001' + name: 'dtdiwaf001' // Non-required parameters diagnosticSettings: [ { @@ -416,7 +448,7 @@ module digitalTwinsInstance 'br/public:avm/res/digital-twins/digital-twins-insta "parameters": { // Required parameters "name": { - "value": "dtdtiwaf001" + "value": "dtdiwaf001" }, // Non-required parameters "diagnosticSettings": { @@ -461,15 +493,15 @@ module digitalTwinsInstance 'br/public:avm/res/digital-twins/digital-twins-insta | :-- | :-- | :-- | | [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | -| [`eventGridEndpoint`](#parameter-eventgridendpoint) | object | Event Grid Endpoint. | -| [`eventHubEndpoint`](#parameter-eventhubendpoint) | object | Event Hub Endpoint. | +| [`eventGridEndpoints`](#parameter-eventgridendpoints) | array | Event Grid Endpoint. | +| [`eventHubEndpoints`](#parameter-eventhubendpoints) | array | Event Hub Endpoint. | | [`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. | | [`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. | | [`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'. | -| [`serviceBusEndpoint`](#parameter-servicebusendpoint) | object | Service Bus Endpoint. | +| [`serviceBusEndpoints`](#parameter-servicebusendpoints) | array | Service Bus Endpoint. | | [`tags`](#parameter-tags) | object | Resource tags. | ### Parameter: `name` @@ -633,21 +665,19 @@ Enable/Disable usage telemetry for module. - Type: bool - Default: `True` -### Parameter: `eventGridEndpoint` +### Parameter: `eventGridEndpoints` Event Grid Endpoint. - Required: No -- Type: object -- Default: `{}` +- Type: array -### Parameter: `eventHubEndpoint` +### Parameter: `eventHubEndpoints` Event Hub Endpoint. - Required: No -- Type: object -- Default: `{}` +- Type: array ### Parameter: `location` @@ -1161,13 +1191,12 @@ The principal type of the assigned principal ID. ] ``` -### Parameter: `serviceBusEndpoint` +### Parameter: `serviceBusEndpoints` Service Bus Endpoint. - Required: No -- Type: object -- Default: `{}` +- Type: array ### Parameter: `tags` diff --git a/avm/res/digital-twins/digital-twins-instance/endpoint--event-hub/README.md b/avm/res/digital-twins/digital-twins-instance/endpoint--event-hub/README.md index 4a9c5acf08..fe0844bdd4 100644 --- a/avm/res/digital-twins/digital-twins-instance/endpoint--event-hub/README.md +++ b/avm/res/digital-twins/digital-twins-instance/endpoint--event-hub/README.md @@ -35,7 +35,7 @@ This module deploys a Digital Twins Instance EventHub Endpoint. | [`deadLetterUri`](#parameter-deadletteruri) | string | Dead letter storage URL for identity-based authentication. | | [`endpointUri`](#parameter-endpointuri) | string | The URL of the EventHub namespace for identity-based authentication. It must include the protocol 'sb://' (i.e. sb://xyz.servicebus.windows.net). | | [`entityPath`](#parameter-entitypath) | string | The EventHub name in the EventHub namespace for identity-based authentication. | -| [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. | +| [`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. | | [`name`](#parameter-name) | string | The name of the Digital Twin Endpoint. | ### Parameter: `connectionStringPrimaryKey` @@ -110,7 +110,7 @@ The EventHub name in the EventHub namespace for identity-based authentication. ### Parameter: `managedIdentities` -The managed identity definition for this resource. +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 @@ -120,7 +120,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. | +| [`userAssignedResourceId`](#parameter-managedidentitiesuserassignedresourceid) | string | The resource ID(s) to assign to the resource. | ### Parameter: `managedIdentities.systemAssigned` @@ -129,12 +129,12 @@ Enables system assigned managed identity on the resource. - Required: No - Type: bool -### Parameter: `managedIdentities.userAssignedResourceIds` +### Parameter: `managedIdentities.userAssignedResourceId` The resource ID(s) to assign to the resource. - Required: No -- Type: array +- Type: string ### Parameter: `name` @@ -152,7 +152,7 @@ The name of the Digital Twin Endpoint. | `name` | string | The name of the Endpoint. | | `resourceGroupName` | string | The name of the resource group the resource was created in. | | `resourceId` | string | The resource ID of the Endpoint. | -| `systemAssignedMIPrincipalId` | string | The principal ID of the system assigned identity. | +| `systemAssignedMIPrincipalId` | string | The principal ID of the system assigned identity. Note: As of 2024-03 is not exported by API. | ## Cross-referenced modules diff --git a/avm/res/digital-twins/digital-twins-instance/endpoint--event-hub/main.bicep b/avm/res/digital-twins/digital-twins-instance/endpoint--event-hub/main.bicep index c2588b6dbf..e5704ff80f 100644 --- a/avm/res/digital-twins/digital-twins-instance/endpoint--event-hub/main.bicep +++ b/avm/res/digital-twins/digital-twins-instance/endpoint--event-hub/main.bicep @@ -36,14 +36,12 @@ param entityPath string = '' @description('Optional. The URL of the EventHub namespace for identity-based authentication. It must include the protocol \'sb://\' (i.e. sb://xyz.servicebus.windows.net).') param endpointUri string = '' -var formattedUserAssignedIdentities = reduce(map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), {}, (cur, next) => union(cur, next)) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } - -@description('Optional. The managed identity definition for this resource.') +@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 var identity = !empty(managedIdentities) ? { - type: (managedIdentities.?systemAssigned ?? false) ? (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : 'None') - userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null + type: (managedIdentities.?systemAssigned ?? false) ? 'SystemAssigned' : (!empty(managedIdentities.?userAssignedResourceId ?? '') ? 'UserAssigned' : null) + userAssignedIdentity: managedIdentities.?userAssignedResourceId } : null resource digitalTwinsInstance 'Microsoft.DigitalTwins/digitalTwinsInstances@2023-01-31' existing = { @@ -75,7 +73,8 @@ output resourceGroupName string = resourceGroup().name @description('The name of the Endpoint.') output name string = endpoint.name -@description('The principal ID of the system assigned identity.') +@description('The principal ID of the system assigned identity. Note: As of 2024-03 is not exported by API.') +#disable-next-line BCP187 output systemAssignedMIPrincipalId string = endpoint.?identity.?principalId ?? '' // =============== // @@ -87,5 +86,5 @@ type managedIdentitiesType = { systemAssigned: bool? @description('Optional. The resource ID(s) to assign to the resource.') - userAssignedResourceIds: string[]? + userAssignedResourceId: string? }? diff --git a/avm/res/digital-twins/digital-twins-instance/endpoint--event-hub/main.json b/avm/res/digital-twins/digital-twins-instance/endpoint--event-hub/main.json index 7da5d6a4ce..77de42e1f5 100644 --- a/avm/res/digital-twins/digital-twins-instance/endpoint--event-hub/main.json +++ b/avm/res/digital-twins/digital-twins-instance/endpoint--event-hub/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.26.54.24096", - "templateHash": "982830653292321499" + "templateHash": "1964184668152537300" }, "name": "Digital Twins Instance EventHub Endpoint", "description": "This module deploys a Digital Twins Instance EventHub Endpoint.", @@ -23,11 +23,8 @@ "description": "Optional. Enables system assigned managed identity on the resource." } }, - "userAssignedResourceIds": { - "type": "array", - "items": { - "type": "string" - }, + "userAssignedResourceId": { + "type": "string", "nullable": true, "metadata": { "description": "Optional. The resource ID(s) to assign to the resource." @@ -107,13 +104,12 @@ "managedIdentities": { "$ref": "#/definitions/managedIdentitiesType", "metadata": { - "description": "Optional. The managed identity definition for this resource." + "description": "Optional. The managed identity definition for this resource. Only one type of identity is supported: system-assigned or user-assigned, but not both." } } }, "variables": { - "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()), 'SystemAssigned', if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceId'), ''))), 'UserAssigned', null())), 'userAssignedIdentity', tryGet(parameters('managedIdentities'), 'userAssignedResourceId')), null())]" }, "resources": { "digitalTwinsInstance": { @@ -167,7 +163,7 @@ "systemAssignedMIPrincipalId": { "type": "string", "metadata": { - "description": "The principal ID of the system assigned identity." + "description": "The principal ID of the system assigned identity. Note: As of 2024-03 is not exported by API." }, "value": "[coalesce(tryGet(tryGet(reference('endpoint', '2023-01-31', 'full'), 'identity'), 'principalId'), '')]" } diff --git a/avm/res/digital-twins/digital-twins-instance/endpoint--service-bus/README.md b/avm/res/digital-twins/digital-twins-instance/endpoint--service-bus/README.md index 2583883f1f..5ea4096614 100644 --- a/avm/res/digital-twins/digital-twins-instance/endpoint--service-bus/README.md +++ b/avm/res/digital-twins/digital-twins-instance/endpoint--service-bus/README.md @@ -34,7 +34,7 @@ This module deploys a Digital Twins Instance ServiceBus Endpoint. | [`deadLetterUri`](#parameter-deadletteruri) | string | Dead letter storage URL for identity-based authentication. | | [`endpointUri`](#parameter-endpointuri) | string | The URL of the ServiceBus namespace for identity-based authentication. It must include the protocol 'sb://' (e.g. sb://xyz.servicebus.windows.net). | | [`entityPath`](#parameter-entitypath) | string | The ServiceBus Topic name for identity-based authentication. | -| [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. | +| [`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. | | [`name`](#parameter-name) | string | The name of the Digital Twin Endpoint. | | [`secondaryConnectionString`](#parameter-secondaryconnectionstring) | securestring | SecondaryConnectionString of the endpoint for key-based authentication. Will be obfuscated during read. Only used if the `authenticationType` is "KeyBased". | @@ -102,7 +102,7 @@ The ServiceBus Topic name for identity-based authentication. ### Parameter: `managedIdentities` -The managed identity definition for this resource. +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 @@ -112,7 +112,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. | +| [`userAssignedResourceId`](#parameter-managedidentitiesuserassignedresourceid) | string | The resource ID(s) to assign to the resource. | ### Parameter: `managedIdentities.systemAssigned` @@ -121,12 +121,12 @@ Enables system assigned managed identity on the resource. - Required: No - Type: bool -### Parameter: `managedIdentities.userAssignedResourceIds` +### Parameter: `managedIdentities.userAssignedResourceId` The resource ID(s) to assign to the resource. - Required: No -- Type: array +- Type: string ### Parameter: `name` @@ -152,7 +152,7 @@ SecondaryConnectionString of the endpoint for key-based authentication. Will be | `name` | string | The name of the Endpoint. | | `resourceGroupName` | string | The name of the resource group the resource was created in. | | `resourceId` | string | The resource ID of the Endpoint. | -| `systemAssignedMIPrincipalId` | string | The principal ID of the system assigned identity. | +| `systemAssignedMIPrincipalId` | string | The principal ID of the system assigned identity. Note: As of 2024-03 is not exported by API. | ## Cross-referenced modules diff --git a/avm/res/digital-twins/digital-twins-instance/endpoint--service-bus/main.bicep b/avm/res/digital-twins/digital-twins-instance/endpoint--service-bus/main.bicep index 7d73f23373..b628349a57 100644 --- a/avm/res/digital-twins/digital-twins-instance/endpoint--service-bus/main.bicep +++ b/avm/res/digital-twins/digital-twins-instance/endpoint--service-bus/main.bicep @@ -36,14 +36,12 @@ param primaryConnectionString string = '' @secure() param secondaryConnectionString string = '' -var formattedUserAssignedIdentities = reduce(map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), {}, (cur, next) => union(cur, next)) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } - -@description('Optional. The managed identity definition for this resource.') +@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 var identity = !empty(managedIdentities) ? { - type: (managedIdentities.?systemAssigned ?? false) ? (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : 'None') - userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null + type: (managedIdentities.?systemAssigned ?? false) ? 'SystemAssigned' : (!empty(managedIdentities.?userAssignedResourceId ?? '') ? 'UserAssigned' : null) + userAssignedIdentity: managedIdentities.?userAssignedResourceId } : null resource digitalTwinsInstance 'Microsoft.DigitalTwins/digitalTwinsInstances@2023-01-31' existing = { @@ -76,7 +74,8 @@ output resourceGroupName string = resourceGroup().name @description('The name of the Endpoint.') output name string = endpoint.name -@description('The principal ID of the system assigned identity.') +@description('The principal ID of the system assigned identity. Note: As of 2024-03 is not exported by API.') +#disable-next-line BCP187 output systemAssignedMIPrincipalId string = endpoint.?identity.?principalId ?? '' // =============== // @@ -88,5 +87,5 @@ type managedIdentitiesType = { systemAssigned: bool? @description('Optional. The resource ID(s) to assign to the resource.') - userAssignedResourceIds: string[]? + userAssignedResourceId: string? }? diff --git a/avm/res/digital-twins/digital-twins-instance/endpoint--service-bus/main.json b/avm/res/digital-twins/digital-twins-instance/endpoint--service-bus/main.json index 52847cffed..b1386e5656 100644 --- a/avm/res/digital-twins/digital-twins-instance/endpoint--service-bus/main.json +++ b/avm/res/digital-twins/digital-twins-instance/endpoint--service-bus/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.26.54.24096", - "templateHash": "18420338400061008774" + "templateHash": "16761257324786961037" }, "name": "Digital Twins Instance ServiceBus Endpoint", "description": "This module deploys a Digital Twins Instance ServiceBus Endpoint.", @@ -23,11 +23,8 @@ "description": "Optional. Enables system assigned managed identity on the resource." } }, - "userAssignedResourceIds": { - "type": "array", - "items": { - "type": "string" - }, + "userAssignedResourceId": { + "type": "string", "nullable": true, "metadata": { "description": "Optional. The resource ID(s) to assign to the resource." @@ -107,13 +104,12 @@ "managedIdentities": { "$ref": "#/definitions/managedIdentitiesType", "metadata": { - "description": "Optional. The managed identity definition for this resource." + "description": "Optional. The managed identity definition for this resource. Only one type of identity is supported: system-assigned or user-assigned, but not both." } } }, "variables": { - "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()), 'SystemAssigned', if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceId'), ''))), 'UserAssigned', null())), 'userAssignedIdentity', tryGet(parameters('managedIdentities'), 'userAssignedResourceId')), null())]" }, "resources": { "digitalTwinsInstance": { @@ -167,7 +163,7 @@ "systemAssignedMIPrincipalId": { "type": "string", "metadata": { - "description": "The principal ID of the system assigned identity." + "description": "The principal ID of the system assigned identity. Note: As of 2024-03 is not exported by API." }, "value": "[coalesce(tryGet(tryGet(reference('endpoint', '2023-01-31', 'full'), 'identity'), 'principalId'), '')]" } diff --git a/avm/res/digital-twins/digital-twins-instance/main.bicep b/avm/res/digital-twins/digital-twins-instance/main.bicep index 2ad665a0fe..6e4b5f81a2 100644 --- a/avm/res/digital-twins/digital-twins-instance/main.bicep +++ b/avm/res/digital-twins/digital-twins-instance/main.bicep @@ -20,13 +20,13 @@ param lock lockType param managedIdentities managedIdentitiesType @description('Optional. Event Hub Endpoint.') -param eventHubEndpoint object = {} +param eventHubEndpoints array? @description('Optional. Event Grid Endpoint.') -param eventGridEndpoint object = {} +param eventGridEndpoints array? @description('Optional. Service Bus Endpoint.') -param serviceBusEndpoint object = {} +param serviceBusEndpoints array? @description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') param privateEndpoints privateEndpointType @@ -93,8 +93,8 @@ resource digitalTwinsInstance 'Microsoft.DigitalTwins/digitalTwinsInstances@2023 } } -module digitalTwinsInstance_eventHubEndpoint 'endpoint--event-hub/main.bicep' = if (!empty(eventHubEndpoint)) { - name: '${uniqueString(deployment().name, location)}-DigitalTwinsInstance-Endpoints-EventHub' +module digitalTwinsInstance_eventHubEndpoints 'endpoint--event-hub/main.bicep' = [for (eventHubEndpoint, index) in (eventHubEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-DigitalTwinsInstance-Endpoints-EventHub-${index}' params: { digitalTwinInstanceName: digitalTwinsInstance.name name: contains(eventHubEndpoint, 'name') ? eventHubEndpoint.name : 'EventHubEndpoint' @@ -107,10 +107,10 @@ module digitalTwinsInstance_eventHubEndpoint 'endpoint--event-hub/main.bicep' = entityPath: contains(eventHubEndpoint, 'entityPath') ? eventHubEndpoint.entityPath : '' managedIdentities: contains(eventHubEndpoint, 'managedIdentities') ? eventHubEndpoint.managedIdentities : {} } -} +}] -module digitalTwinsInstance_eventGridEndpoint 'endpoint--event-grid/main.bicep' = if (!empty(eventGridEndpoint)) { - name: '${uniqueString(deployment().name, location)}-DigitalTwinsInstance-Endpoints-EventGrid' +module digitalTwinsInstance_eventGridEndpoints 'endpoint--event-grid/main.bicep' = [for (eventGridEndpoint, index) in (eventGridEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-DigitalTwinsInstance-Endpoints-EventGrid-${index}' params: { digitalTwinInstanceName: digitalTwinsInstance.name name: contains(eventGridEndpoint, 'name') ? eventGridEndpoint.name : 'EventGridEndpoint' @@ -119,10 +119,10 @@ module digitalTwinsInstance_eventGridEndpoint 'endpoint--event-grid/main.bicep' deadLetterUri: contains(eventGridEndpoint, 'deadLetterUri') ? eventGridEndpoint.deadLetterUri : '' eventGridDomainResourceId: contains(eventGridEndpoint, 'eventGridDomainId') ? eventGridEndpoint.eventGridDomainId : '' } -} +}] -module digitalTwinsInstance_serviceBusEndpoint 'endpoint--service-bus/main.bicep' = if (!empty(serviceBusEndpoint)) { - name: '${uniqueString(deployment().name, location)}-DigitalTwinsInstance-Endpoints-ServiceBus' +module digitalTwinsInstance_serviceBusEndpoints 'endpoint--service-bus/main.bicep' = [for (serviceBusEndpoint, index) in (serviceBusEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-DigitalTwinsInstance-Endpoints-ServiceBus-${index}' params: { digitalTwinInstanceName: digitalTwinsInstance.name name: contains(serviceBusEndpoint, 'name') ? serviceBusEndpoint.name : 'ServiceBusEndpoint' @@ -135,7 +135,7 @@ module digitalTwinsInstance_serviceBusEndpoint 'endpoint--service-bus/main.bicep secondaryConnectionString: contains(serviceBusEndpoint, 'secondaryConnectionString') ? serviceBusEndpoint.secondaryConnectionString : '' managedIdentities: contains(serviceBusEndpoint, 'managedIdentities') ? serviceBusEndpoint.managedIdentities : {} } -} +}] module digitalTwinsInstance_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { name: '${uniqueString(deployment().name, location)}-DigitalTwinsInstance-PrivateEndpoint-${index}' diff --git a/avm/res/digital-twins/digital-twins-instance/main.json b/avm/res/digital-twins/digital-twins-instance/main.json index b845ff6813..7ac9717e3e 100644 --- a/avm/res/digital-twins/digital-twins-instance/main.json +++ b/avm/res/digital-twins/digital-twins-instance/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.26.54.24096", - "templateHash": "5068998297960417598" + "templateHash": "1024174644495719338" }, "name": "Digital Twins Instances", "description": "This module deploys an Azure Digital Twins Instance.", @@ -473,23 +473,23 @@ "description": "Optional. The managed identity definition for this resource." } }, - "eventHubEndpoint": { - "type": "object", - "defaultValue": {}, + "eventHubEndpoints": { + "type": "array", + "nullable": true, "metadata": { "description": "Optional. Event Hub Endpoint." } }, - "eventGridEndpoint": { - "type": "object", - "defaultValue": {}, + "eventGridEndpoints": { + "type": "array", + "nullable": true, "metadata": { "description": "Optional. Event Grid Endpoint." } }, - "serviceBusEndpoint": { - "type": "object", - "defaultValue": {}, + "serviceBusEndpoints": { + "type": "array", + "nullable": true, "metadata": { "description": "Optional. Service Bus Endpoint." } @@ -654,11 +654,14 @@ "digitalTwinsInstance" ] }, - "digitalTwinsInstance_eventHubEndpoint": { - "condition": "[not(empty(parameters('eventHubEndpoint')))]", + "digitalTwinsInstance_eventHubEndpoints": { + "copy": { + "name": "digitalTwinsInstance_eventHubEndpoints", + "count": "[length(coalesce(parameters('eventHubEndpoints'), createArray()))]" + }, "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", - "name": "[format('{0}-DigitalTwinsInstance-Endpoints-EventHub', uniqueString(deployment().name, parameters('location')))]", + "name": "[format('{0}-DigitalTwinsInstance-Endpoints-EventHub-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", "properties": { "expressionEvaluationOptions": { "scope": "inner" @@ -668,15 +671,15 @@ "digitalTwinInstanceName": { "value": "[parameters('name')]" }, - "name": "[if(contains(parameters('eventHubEndpoint'), 'name'), createObject('value', parameters('eventHubEndpoint').name), createObject('value', 'EventHubEndpoint'))]", - "authenticationType": "[if(contains(parameters('eventHubEndpoint'), 'authenticationType'), createObject('value', parameters('eventHubEndpoint').authenticationType), createObject('value', 'KeyBased'))]", - "connectionStringPrimaryKey": "[if(contains(parameters('eventHubEndpoint'), 'connectionStringPrimaryKey'), createObject('value', parameters('eventHubEndpoint').connectionStringPrimaryKey), createObject('value', ''))]", - "connectionStringSecondaryKey": "[if(contains(parameters('eventHubEndpoint'), 'connectionStringSecondaryKey'), createObject('value', parameters('eventHubEndpoint').connectionStringSecondaryKey), createObject('value', ''))]", - "deadLetterSecret": "[if(contains(parameters('eventHubEndpoint'), 'deadLetterSecret'), createObject('value', parameters('eventHubEndpoint').deadLetterSecret), createObject('value', ''))]", - "deadLetterUri": "[if(contains(parameters('eventHubEndpoint'), 'deadLetterUri'), createObject('value', parameters('eventHubEndpoint').deadLetterUri), createObject('value', ''))]", - "endpointUri": "[if(contains(parameters('eventHubEndpoint'), 'endpointUri'), createObject('value', parameters('eventHubEndpoint').endpointUri), createObject('value', ''))]", - "entityPath": "[if(contains(parameters('eventHubEndpoint'), 'entityPath'), createObject('value', parameters('eventHubEndpoint').entityPath), createObject('value', ''))]", - "managedIdentities": "[if(contains(parameters('eventHubEndpoint'), 'managedIdentities'), createObject('value', parameters('eventHubEndpoint').managedIdentities), createObject('value', createObject()))]" + "name": "[if(contains(coalesce(parameters('eventHubEndpoints'), createArray())[copyIndex()], 'name'), createObject('value', coalesce(parameters('eventHubEndpoints'), createArray())[copyIndex()].name), createObject('value', 'EventHubEndpoint'))]", + "authenticationType": "[if(contains(coalesce(parameters('eventHubEndpoints'), createArray())[copyIndex()], 'authenticationType'), createObject('value', coalesce(parameters('eventHubEndpoints'), createArray())[copyIndex()].authenticationType), createObject('value', 'KeyBased'))]", + "connectionStringPrimaryKey": "[if(contains(coalesce(parameters('eventHubEndpoints'), createArray())[copyIndex()], 'connectionStringPrimaryKey'), createObject('value', coalesce(parameters('eventHubEndpoints'), createArray())[copyIndex()].connectionStringPrimaryKey), createObject('value', ''))]", + "connectionStringSecondaryKey": "[if(contains(coalesce(parameters('eventHubEndpoints'), createArray())[copyIndex()], 'connectionStringSecondaryKey'), createObject('value', coalesce(parameters('eventHubEndpoints'), createArray())[copyIndex()].connectionStringSecondaryKey), createObject('value', ''))]", + "deadLetterSecret": "[if(contains(coalesce(parameters('eventHubEndpoints'), createArray())[copyIndex()], 'deadLetterSecret'), createObject('value', coalesce(parameters('eventHubEndpoints'), createArray())[copyIndex()].deadLetterSecret), createObject('value', ''))]", + "deadLetterUri": "[if(contains(coalesce(parameters('eventHubEndpoints'), createArray())[copyIndex()], 'deadLetterUri'), createObject('value', coalesce(parameters('eventHubEndpoints'), createArray())[copyIndex()].deadLetterUri), createObject('value', ''))]", + "endpointUri": "[if(contains(coalesce(parameters('eventHubEndpoints'), createArray())[copyIndex()], 'endpointUri'), createObject('value', coalesce(parameters('eventHubEndpoints'), createArray())[copyIndex()].endpointUri), createObject('value', ''))]", + "entityPath": "[if(contains(coalesce(parameters('eventHubEndpoints'), createArray())[copyIndex()], 'entityPath'), createObject('value', coalesce(parameters('eventHubEndpoints'), createArray())[copyIndex()].entityPath), createObject('value', ''))]", + "managedIdentities": "[if(contains(coalesce(parameters('eventHubEndpoints'), createArray())[copyIndex()], 'managedIdentities'), createObject('value', coalesce(parameters('eventHubEndpoints'), createArray())[copyIndex()].managedIdentities), createObject('value', createObject()))]" }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -686,7 +689,7 @@ "_generator": { "name": "bicep", "version": "0.26.54.24096", - "templateHash": "982830653292321499" + "templateHash": "1964184668152537300" }, "name": "Digital Twins Instance EventHub Endpoint", "description": "This module deploys a Digital Twins Instance EventHub Endpoint.", @@ -703,11 +706,8 @@ "description": "Optional. Enables system assigned managed identity on the resource." } }, - "userAssignedResourceIds": { - "type": "array", - "items": { - "type": "string" - }, + "userAssignedResourceId": { + "type": "string", "nullable": true, "metadata": { "description": "Optional. The resource ID(s) to assign to the resource." @@ -787,13 +787,12 @@ "managedIdentities": { "$ref": "#/definitions/managedIdentitiesType", "metadata": { - "description": "Optional. The managed identity definition for this resource." + "description": "Optional. The managed identity definition for this resource. Only one type of identity is supported: system-assigned or user-assigned, but not both." } } }, "variables": { - "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()), 'SystemAssigned', if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceId'), ''))), 'UserAssigned', null())), 'userAssignedIdentity', tryGet(parameters('managedIdentities'), 'userAssignedResourceId')), null())]" }, "resources": { "digitalTwinsInstance": { @@ -847,7 +846,7 @@ "systemAssignedMIPrincipalId": { "type": "string", "metadata": { - "description": "The principal ID of the system assigned identity." + "description": "The principal ID of the system assigned identity. Note: As of 2024-03 is not exported by API." }, "value": "[coalesce(tryGet(tryGet(reference('endpoint', '2023-01-31', 'full'), 'identity'), 'principalId'), '')]" } @@ -858,11 +857,14 @@ "digitalTwinsInstance" ] }, - "digitalTwinsInstance_eventGridEndpoint": { - "condition": "[not(empty(parameters('eventGridEndpoint')))]", + "digitalTwinsInstance_eventGridEndpoints": { + "copy": { + "name": "digitalTwinsInstance_eventGridEndpoints", + "count": "[length(coalesce(parameters('eventGridEndpoints'), createArray()))]" + }, "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", - "name": "[format('{0}-DigitalTwinsInstance-Endpoints-EventGrid', uniqueString(deployment().name, parameters('location')))]", + "name": "[format('{0}-DigitalTwinsInstance-Endpoints-EventGrid-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", "properties": { "expressionEvaluationOptions": { "scope": "inner" @@ -872,11 +874,11 @@ "digitalTwinInstanceName": { "value": "[parameters('name')]" }, - "name": "[if(contains(parameters('eventGridEndpoint'), 'name'), createObject('value', parameters('eventGridEndpoint').name), createObject('value', 'EventGridEndpoint'))]", - "topicEndpoint": "[if(contains(parameters('eventGridEndpoint'), 'topicEndpoint'), createObject('value', parameters('eventGridEndpoint').topicEndpoint), createObject('value', ''))]", - "deadLetterSecret": "[if(contains(parameters('eventGridEndpoint'), 'deadLetterSecret'), createObject('value', parameters('eventGridEndpoint').deadLetterSecret), createObject('value', ''))]", - "deadLetterUri": "[if(contains(parameters('eventGridEndpoint'), 'deadLetterUri'), createObject('value', parameters('eventGridEndpoint').deadLetterUri), createObject('value', ''))]", - "eventGridDomainResourceId": "[if(contains(parameters('eventGridEndpoint'), 'eventGridDomainId'), createObject('value', parameters('eventGridEndpoint').eventGridDomainId), createObject('value', ''))]" + "name": "[if(contains(coalesce(parameters('eventGridEndpoints'), createArray())[copyIndex()], 'name'), createObject('value', coalesce(parameters('eventGridEndpoints'), createArray())[copyIndex()].name), createObject('value', 'EventGridEndpoint'))]", + "topicEndpoint": "[if(contains(coalesce(parameters('eventGridEndpoints'), createArray())[copyIndex()], 'topicEndpoint'), createObject('value', coalesce(parameters('eventGridEndpoints'), createArray())[copyIndex()].topicEndpoint), createObject('value', ''))]", + "deadLetterSecret": "[if(contains(coalesce(parameters('eventGridEndpoints'), createArray())[copyIndex()], 'deadLetterSecret'), createObject('value', coalesce(parameters('eventGridEndpoints'), createArray())[copyIndex()].deadLetterSecret), createObject('value', ''))]", + "deadLetterUri": "[if(contains(coalesce(parameters('eventGridEndpoints'), createArray())[copyIndex()], 'deadLetterUri'), createObject('value', coalesce(parameters('eventGridEndpoints'), createArray())[copyIndex()].deadLetterUri), createObject('value', ''))]", + "eventGridDomainResourceId": "[if(contains(coalesce(parameters('eventGridEndpoints'), createArray())[copyIndex()], 'eventGridDomainId'), createObject('value', coalesce(parameters('eventGridEndpoints'), createArray())[copyIndex()].eventGridDomainId), createObject('value', ''))]" }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -977,11 +979,14 @@ "digitalTwinsInstance" ] }, - "digitalTwinsInstance_serviceBusEndpoint": { - "condition": "[not(empty(parameters('serviceBusEndpoint')))]", + "digitalTwinsInstance_serviceBusEndpoints": { + "copy": { + "name": "digitalTwinsInstance_serviceBusEndpoints", + "count": "[length(coalesce(parameters('serviceBusEndpoints'), createArray()))]" + }, "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", - "name": "[format('{0}-DigitalTwinsInstance-Endpoints-ServiceBus', uniqueString(deployment().name, parameters('location')))]", + "name": "[format('{0}-DigitalTwinsInstance-Endpoints-ServiceBus-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", "properties": { "expressionEvaluationOptions": { "scope": "inner" @@ -991,15 +996,15 @@ "digitalTwinInstanceName": { "value": "[parameters('name')]" }, - "name": "[if(contains(parameters('serviceBusEndpoint'), 'name'), createObject('value', parameters('serviceBusEndpoint').name), createObject('value', 'ServiceBusEndpoint'))]", - "authenticationType": "[if(contains(parameters('serviceBusEndpoint'), 'authenticationType'), createObject('value', parameters('serviceBusEndpoint').authenticationType), createObject('value', ''))]", - "deadLetterSecret": "[if(contains(parameters('serviceBusEndpoint'), 'deadLetterSecret'), createObject('value', parameters('serviceBusEndpoint').deadLetterSecret), createObject('value', ''))]", - "deadLetterUri": "[if(contains(parameters('serviceBusEndpoint'), 'deadLetterUri'), createObject('value', parameters('serviceBusEndpoint').deadLetterUri), createObject('value', ''))]", - "endpointUri": "[if(contains(parameters('serviceBusEndpoint'), 'endpointUri'), createObject('value', parameters('serviceBusEndpoint').endpointUri), createObject('value', ''))]", - "entityPath": "[if(contains(parameters('serviceBusEndpoint'), 'entityPath'), createObject('value', parameters('serviceBusEndpoint').entityPath), createObject('value', ''))]", - "primaryConnectionString": "[if(contains(parameters('serviceBusEndpoint'), 'primaryConnectionString'), createObject('value', parameters('serviceBusEndpoint').primaryConnectionString), createObject('value', ''))]", - "secondaryConnectionString": "[if(contains(parameters('serviceBusEndpoint'), 'secondaryConnectionString'), createObject('value', parameters('serviceBusEndpoint').secondaryConnectionString), createObject('value', ''))]", - "managedIdentities": "[if(contains(parameters('serviceBusEndpoint'), 'managedIdentities'), createObject('value', parameters('serviceBusEndpoint').managedIdentities), createObject('value', createObject()))]" + "name": "[if(contains(coalesce(parameters('serviceBusEndpoints'), createArray())[copyIndex()], 'name'), createObject('value', coalesce(parameters('serviceBusEndpoints'), createArray())[copyIndex()].name), createObject('value', 'ServiceBusEndpoint'))]", + "authenticationType": "[if(contains(coalesce(parameters('serviceBusEndpoints'), createArray())[copyIndex()], 'authenticationType'), createObject('value', coalesce(parameters('serviceBusEndpoints'), createArray())[copyIndex()].authenticationType), createObject('value', ''))]", + "deadLetterSecret": "[if(contains(coalesce(parameters('serviceBusEndpoints'), createArray())[copyIndex()], 'deadLetterSecret'), createObject('value', coalesce(parameters('serviceBusEndpoints'), createArray())[copyIndex()].deadLetterSecret), createObject('value', ''))]", + "deadLetterUri": "[if(contains(coalesce(parameters('serviceBusEndpoints'), createArray())[copyIndex()], 'deadLetterUri'), createObject('value', coalesce(parameters('serviceBusEndpoints'), createArray())[copyIndex()].deadLetterUri), createObject('value', ''))]", + "endpointUri": "[if(contains(coalesce(parameters('serviceBusEndpoints'), createArray())[copyIndex()], 'endpointUri'), createObject('value', coalesce(parameters('serviceBusEndpoints'), createArray())[copyIndex()].endpointUri), createObject('value', ''))]", + "entityPath": "[if(contains(coalesce(parameters('serviceBusEndpoints'), createArray())[copyIndex()], 'entityPath'), createObject('value', coalesce(parameters('serviceBusEndpoints'), createArray())[copyIndex()].entityPath), createObject('value', ''))]", + "primaryConnectionString": "[if(contains(coalesce(parameters('serviceBusEndpoints'), createArray())[copyIndex()], 'primaryConnectionString'), createObject('value', coalesce(parameters('serviceBusEndpoints'), createArray())[copyIndex()].primaryConnectionString), createObject('value', ''))]", + "secondaryConnectionString": "[if(contains(coalesce(parameters('serviceBusEndpoints'), createArray())[copyIndex()], 'secondaryConnectionString'), createObject('value', coalesce(parameters('serviceBusEndpoints'), createArray())[copyIndex()].secondaryConnectionString), createObject('value', ''))]", + "managedIdentities": "[if(contains(coalesce(parameters('serviceBusEndpoints'), createArray())[copyIndex()], 'managedIdentities'), createObject('value', coalesce(parameters('serviceBusEndpoints'), createArray())[copyIndex()].managedIdentities), createObject('value', createObject()))]" }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -1009,7 +1014,7 @@ "_generator": { "name": "bicep", "version": "0.26.54.24096", - "templateHash": "18420338400061008774" + "templateHash": "16761257324786961037" }, "name": "Digital Twins Instance ServiceBus Endpoint", "description": "This module deploys a Digital Twins Instance ServiceBus Endpoint.", @@ -1026,11 +1031,8 @@ "description": "Optional. Enables system assigned managed identity on the resource." } }, - "userAssignedResourceIds": { - "type": "array", - "items": { - "type": "string" - }, + "userAssignedResourceId": { + "type": "string", "nullable": true, "metadata": { "description": "Optional. The resource ID(s) to assign to the resource." @@ -1110,13 +1112,12 @@ "managedIdentities": { "$ref": "#/definitions/managedIdentitiesType", "metadata": { - "description": "Optional. The managed identity definition for this resource." + "description": "Optional. The managed identity definition for this resource. Only one type of identity is supported: system-assigned or user-assigned, but not both." } } }, "variables": { - "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()), 'SystemAssigned', if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceId'), ''))), 'UserAssigned', null())), 'userAssignedIdentity', tryGet(parameters('managedIdentities'), 'userAssignedResourceId')), null())]" }, "resources": { "digitalTwinsInstance": { @@ -1170,7 +1171,7 @@ "systemAssignedMIPrincipalId": { "type": "string", "metadata": { - "description": "The principal ID of the system assigned identity." + "description": "The principal ID of the system assigned identity. Note: As of 2024-03 is not exported by API." }, "value": "[coalesce(tryGet(tryGet(reference('endpoint', '2023-01-31', 'full'), 'identity'), 'principalId'), '')]" } diff --git a/avm/res/digital-twins/digital-twins-instance/tests/e2e/defaults/main.test.bicep b/avm/res/digital-twins/digital-twins-instance/tests/e2e/defaults/main.test.bicep index bcbf4637ac..45d96c80d6 100644 --- a/avm/res/digital-twins/digital-twins-instance/tests/e2e/defaults/main.test.bicep +++ b/avm/res/digital-twins/digital-twins-instance/tests/e2e/defaults/main.test.bicep @@ -15,7 +15,7 @@ param resourceGroupName string = 'dep-${namePrefix}-digitaltwins.digitaltwinsins 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 = 'dtdtimin' +param serviceShort string = 'dtdimin' @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' diff --git a/avm/res/digital-twins/digital-twins-instance/tests/e2e/max/main.test.bicep b/avm/res/digital-twins/digital-twins-instance/tests/e2e/max/main.test.bicep index 4fcd43e149..df9a656305 100644 --- a/avm/res/digital-twins/digital-twins-instance/tests/e2e/max/main.test.bicep +++ b/avm/res/digital-twins/digital-twins-instance/tests/e2e/max/main.test.bicep @@ -15,7 +15,7 @@ param resourceGroupName string = 'dep-${namePrefix}-digitaltwins.digitaltwinsins 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 = 'dtdtimax' +param serviceShort string = 'dtdmax' @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' @@ -38,10 +38,10 @@ module nestedDependencies 'dependencies.bicep' = { location: resourceLocation virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' - eventHubName: 'dt-${uniqueString(serviceShort)}-evh-01' - eventHubNamespaceName: 'dt-${uniqueString(serviceShort)}-evhns-01' - serviceBusName: 'dt-${uniqueString(serviceShort)}-sb-01' - eventGridDomainName: 'dt-${uniqueString(serviceShort)}-evg-01' + eventHubName: 'dt-${serviceShort}-evh-01' + eventHubNamespaceName: 'dt-${serviceShort}-evhns-01' + serviceBusName: 'dt-${serviceShort}-sb-01' + eventGridDomainName: 'dt-${serviceShort}-evg-01' } } @@ -53,8 +53,8 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t params: { storageAccountName: 'dep${namePrefix}diasa${serviceShort}03' logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' - eventHubNamespaceEventHubName: 'dep-${uniqueString(serviceShort)}-evh-01' - eventHubNamespaceName: 'dep-${uniqueString(serviceShort)}-evh-01' + eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}01' + eventHubNamespaceName: 'dep-${namePrefix}-evhns-${serviceShort}01' location: resourceLocation } } @@ -68,34 +68,49 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' params: { - location: resourceLocation - eventHubEndpoint: { - authenticationType: 'IdentityBased' - endpointUri: 'sb://${nestedDependencies.outputs.eventhubNamespaceName}.servicebus.windows.net/' - entityPath: nestedDependencies.outputs.eventhubName - managedIdentities: { - userAssignedResourceId: nestedDependencies.outputs.managedIdentityResourceId - } - } - serviceBusEndpoint: { - authenticationType: 'IdentityBased' - endpointUri: 'sb://${nestedDependencies.outputs.serviceBusName}.servicebus.windows.net/' - entityPath: nestedDependencies.outputs.serviceBusTopicName - managedIdentities: { - userAssignedResourceId: nestedDependencies.outputs.managedIdentityResourceId - } - } - eventGridEndpoint: { - eventGridDomainId: nestedDependencies.outputs.eventGridDomainResourceId - topicEndpoint: nestedDependencies.outputs.eventGridEndpoint - } name: '${namePrefix}${serviceShort}001' + location: resourceLocation managedIdentities: { systemAssigned: true userAssignedResourceIds: [ nestedDependencies.outputs.managedIdentityResourceId ] } + eventHubEndpoints: [ + { + authenticationType: 'IdentityBased' + endpointUri: 'sb://${nestedDependencies.outputs.eventhubNamespaceName}.servicebus.windows.net/' + entityPath: nestedDependencies.outputs.eventhubName + managedIdentities: { + userAssignedResourceId: nestedDependencies.outputs.managedIdentityResourceId + } + } + ] + serviceBusEndpoints: [ + { + name: 'ServiceBusPrimary' + authenticationType: 'IdentityBased' + endpointUri: 'sb://${nestedDependencies.outputs.serviceBusName}.servicebus.windows.net/' + entityPath: nestedDependencies.outputs.serviceBusTopicName + managedIdentities: { + userAssignedResourceId: nestedDependencies.outputs.managedIdentityResourceId + } + } + { + name: 'ServiceBusSeconday' + authenticationType: 'IdentityBased' + endpointUri: 'sb://${nestedDependencies.outputs.serviceBusName}.servicebus.windows.net/' + entityPath: nestedDependencies.outputs.serviceBusTopicName + managedIdentities: { + systemAssigned: true + } + } + ] + eventGridEndpoints: [ { + eventGridDomainId: nestedDependencies.outputs.eventGridDomainResourceId + topicEndpoint: nestedDependencies.outputs.eventGridEndpoint + } + ] diagnosticSettings: [ { name: 'customSetting' diff --git a/avm/res/digital-twins/digital-twins-instance/tests/e2e/pe/main.test.bicep b/avm/res/digital-twins/digital-twins-instance/tests/e2e/pe/main.test.bicep index 7e1e67efda..dfef52207a 100644 --- a/avm/res/digital-twins/digital-twins-instance/tests/e2e/pe/main.test.bicep +++ b/avm/res/digital-twins/digital-twins-instance/tests/e2e/pe/main.test.bicep @@ -15,7 +15,7 @@ param resourceGroupName string = 'dep-${namePrefix}-digitaltwins.digitaltwinsins 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 = 'dtdtipep' +param serviceShort string = 'dtdpep' @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' diff --git a/avm/res/digital-twins/digital-twins-instance/tests/e2e/waf-aligned/main.test.bicep b/avm/res/digital-twins/digital-twins-instance/tests/e2e/waf-aligned/main.test.bicep index ce1cc5197b..a8e66b0fe6 100644 --- a/avm/res/digital-twins/digital-twins-instance/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/digital-twins/digital-twins-instance/tests/e2e/waf-aligned/main.test.bicep @@ -15,7 +15,7 @@ param resourceGroupName string = 'dep-${namePrefix}-digitaltwins.digitaltwinsins 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 = 'dtdtiwaf' +param serviceShort string = 'dtdiwaf' @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' @@ -39,8 +39,8 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t params: { storageAccountName: 'dep${namePrefix}diasa${serviceShort}03' logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' - eventHubNamespaceEventHubName: 'dep-${uniqueString(serviceShort)}-evh-01' - eventHubNamespaceName: 'dep-${uniqueString(serviceShort)}-evh-01' + eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}01' + eventHubNamespaceName: 'dep-${namePrefix}-evhns-${serviceShort}01' location: resourceLocation } } From ffe5167b2820ea66a9eee56914ee57f458afdda0 Mon Sep 17 00:00:00 2001 From: Alexander Sehr Date: Mon, 25 Mar 2024 17:42:24 +0100 Subject: [PATCH 61/73] fix: Fixed module tests to align with V2 formatter (while still working with V1) (#1409) ## Description - Fixed module tests to align with V2 formatter (while still working with V1) - To be precise: Updated the regex to work with both formats ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.analysis-services.server](https://github.com/AlexanderSehr/bicep-registry-modules/actions/workflows/avm.res.analysis-services.server.yml/badge.svg?branch=users%2Falsehr%2FmoduleTestsFix&event=workflow_dispatch)](https://github.com/AlexanderSehr/bicep-registry-modules/actions/workflows/avm.res.analysis-services.server.yml) | | [![avm.res.key-vault.vault](https://github.com/AlexanderSehr/bicep-registry-modules/actions/workflows/avm.res.key-vault.vault.yml/badge.svg?branch=users%2Falsehr%2FmoduleTestsFix&event=workflow_dispatch)](https://github.com/AlexanderSehr/bicep-registry-modules/actions/workflows/avm.res.key-vault.vault.yml) | ## Type of Change - [x] Update to CI Environment or utlities (Non-module effecting changes) - [ ] Azure Verified Module updates: - [ ] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation --------- Co-authored-by: Erika Gressi <56914614+eriqua@users.noreply.github.com> --- .../pipelines/staticValidation/compliance/module.tests.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 index 4880560c0c..2c82eb4852 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 @@ -1279,13 +1279,13 @@ Describe 'Test file tests' -Tag 'TestTemplate' { ($testFileContent | Out-String) | Should -Match "param namePrefix string = '#_namePrefix_#'" -Because 'The test CI needs this value to ensure that deployed resources have unique names per fork.' } - It "[] Bicep test deployment files should invoke test like [`module testDeployment '../.*main.bicep' = {`] for test case []" -TestCases $deploymentTestFileTestCases { + It "[] Bicep test deployment files should invoke test like [`module testDeployment '../.*main.bicep' = [ or {`] for test case []" -TestCases $deploymentTestFileTestCases { param( [object[]] $testFileContent ) - $testIndex = ($testFileContent | Select-String ("^module testDeployment '..\/.*main.bicep' = (\[for .+: )?{$") | ForEach-Object { $_.LineNumber - 1 })[0] + $testIndex = ($testFileContent | Select-String ("^module testDeployment '..\/.*main.bicep' = .*[\[|\{]$") | ForEach-Object { $_.LineNumber - 1 })[0] $testIndex -ne -1 | Should -Be $true -Because 'the module test invocation should be in the expected format to allow identification.' } From 57722ea93ba8686c868c46d003e098ebc377afe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Barab=C3=A1s?= Date: Mon, 25 Mar 2024 13:35:54 -0700 Subject: [PATCH 62/73] chore: triage automation fix (#1410) ## Description This PR fixes a few typos, as well as removes ITA16 that was accidentally added (this is only needed in the AVM repo). --- .github/policies/eventResponder.yml | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/.github/policies/eventResponder.yml b/.github/policies/eventResponder.yml index 431a332691..b72029b8ea 100644 --- a/.github/policies/eventResponder.yml +++ b/.github/policies/eventResponder.yml @@ -20,7 +20,7 @@ configuration: - addReply: reply: | > [!IMPORTANT] - > **The "Needs: Triage :mag:" label must be removed once the triage process is complete !** + > **The "Needs: Triage :mag:" label must be removed once the triage process is complete!** > [!TIP] > For additional guidance on how to triage this issue/PR, see the [BRM Issue Triage](https://azure.github.io/Azure-Verified-Modules/help-support/issue-triage/brm-issue-triage/) documentation. @@ -157,24 +157,6 @@ configuration: > [!NOTE] > The "Needs: Triage :mag:" label was removed as per [ITA15](https://azure.github.io/Azure-Verified-Modules/help-support/issue-triage/issue-triage-automation/#ita15). - - description: 'ITA16 - Add the "Status: Owners Identified :metal:" label when someone is assigned to a Module Proposal' - if: - - payloadType: Issues - - not: - isAction: - action: Closed - - hasLabel: - label: "Type: New Module Proposal :bulb:" - - isAssignedToSomeone - then: - - addLabel: - label: "Status: Owners Identified :metal:" - - addReply: - reply: | - > [!NOTE] - > The "Status: Owners Identified :metal:" label was added as per [ITA15](https://azure.github.io/Azure-Verified-Modules/help-support/issue-triage/issue-triage-automation/#ita15). - triggerOnOwnActions: true - - description: 'ITA20 - If the type is feature request, assign the "Type: Feature Request :heavy_plus_sign:" label on the issue' if: - payloadType: Issues From 0bb60e91e86b7e035e037e3200d0ff6630fd8858 Mon Sep 17 00:00:00 2001 From: Kris Baranek Date: Tue, 26 Mar 2024 00:13:30 +0100 Subject: [PATCH 63/73] fix: fixed Bicep warning caused by the identity type (#1238) ## Description Fixed BCP321 warning caused by the `identity` variable in multiple modules. ![image](https://github.com/Azure/bicep-registry-modules/assets/20225789/080e4b1c-b934-4e4a-807e-0e2557eab5f4) ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.api-management.service](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.api-management.service.yml/badge.svg?branch=users%2Fkrbar%2FidentityWarningFix)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.api-management.service.yml) | | [![avm.res.app.container-app](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.app.container-app.yml/badge.svg?branch=users%2Fkrbar%2FidentityWarningFix)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.app.container-app.yml) | | [![avm.res.batch.batch-account](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.batch.batch-account.yml/badge.svg?branch=users%2Fkrbar%2FidentityWarningFix)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.batch.batch-account.yml) | | [![avm.res.cache.redis](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.cache.redis.yml/badge.svg?branch=users%2Fkrbar%2FidentityWarningFix)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.cache.redis.yml) | | [![avm.res.data-factory.factory](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.data-factory.factory.yml/badge.svg?branch=users%2Fkrbar%2FidentityWarningFix)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.data-factory.factory.yml) | | [![avm.res.databricks.access-connector](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.databricks.access-connector.yml/badge.svg?branch=users%2Fkrbar%2FidentityWarningFix)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.databricks.access-connector.yml) | | [![avm.res.db-for-postgre-sql.flexible-server](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.db-for-postgre-sql.flexible-server.yml/badge.svg?branch=users%2Fkrbar%2FidentityWarningFix)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.db-for-postgre-sql.flexible-server.yml) | | [![avm.res.logic.workflow](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.logic.workflow.yml/badge.svg?branch=users%2Fkrbar%2FidentityWarningFix)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.logic.workflow.yml) | | [![avm.res.net-app.net-app-account](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.net-app.net-app-account.yml/badge.svg?branch=users%2Fkrbar%2FidentityWarningFix)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.net-app.net-app-account.yml) | | [![avm.res.storage.storage-account](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.storage.storage-account.yml/badge.svg?branch=users%2Fkrbar%2FidentityWarningFix)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.storage.storage-account.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [x] Azure Verified Module updates: - [x] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [x] I have run `Set-AVMModule` locally to generate the supporting module files. - [x] My corresponding pipelines / checks run clean and green without any errors or warnings --- avm/res/api-management/service/main.bicep | 2 +- avm/res/api-management/service/main.json | 62 +++++++++---------- avm/res/app/container-app/main.bicep | 2 +- avm/res/app/container-app/main.json | 6 +- avm/res/batch/batch-account/main.bicep | 2 +- avm/res/batch/batch-account/main.json | 6 +- avm/res/cache/redis/main.bicep | 2 +- avm/res/cache/redis/main.json | 6 +- avm/res/data-factory/factory/main.bicep | 2 +- avm/res/data-factory/factory/main.json | 4 +- .../databricks/access-connector/main.bicep | 2 +- avm/res/databricks/access-connector/main.json | 6 +- .../flexible-server/main.bicep | 2 +- .../flexible-server/main.json | 22 +++---- avm/res/logic/workflow/main.bicep | 2 +- avm/res/logic/workflow/main.json | 6 +- .../net-app-account/capacity-pool/README.md | 4 +- .../net-app-account/capacity-pool/main.json | 8 +-- .../capacity-pool/volume/README.md | 2 +- .../capacity-pool/volume/main.json | 4 +- avm/res/net-app/net-app-account/main.bicep | 2 +- avm/res/net-app/net-app-account/main.json | 14 ++--- avm/res/storage/storage-account/main.bicep | 2 +- avm/res/storage/storage-account/main.json | 54 ++++++++-------- 24 files changed, 112 insertions(+), 112 deletions(-) diff --git a/avm/res/api-management/service/main.bicep b/avm/res/api-management/service/main.bicep index dcc0cd05e7..5817da80a9 100644 --- a/avm/res/api-management/service/main.bicep +++ b/avm/res/api-management/service/main.bicep @@ -133,7 +133,7 @@ var authorizationServerList = !empty(authorizationServers) ? authorizationServer 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) + type: (managedIdentities.?systemAssigned ?? false) ? (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : 'None') userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null } : null diff --git a/avm/res/api-management/service/main.json b/avm/res/api-management/service/main.json index 170cb02392..9f44ef9ee9 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.25.53.49325", - "templateHash": "8102357484603903216" + "version": "0.26.54.24096", + "templateHash": "4652975451954294914" }, "name": "API Management Services", "description": "This module deploys an API Management Service.", @@ -515,7 +515,7 @@ "variables": { "authorizationServerList": "[if(not(empty(parameters('authorizationServers'))), parameters('authorizationServers').secureList, createArray())]", "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())]", + "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": { "API Management Developer Portal Content Editor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c031e6a8-4391-4de0-8d69-4706a7ed3729')]", "API Management Service Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '312a565d-c81f-4fd8-895a-4e21e48d571c')]", @@ -745,8 +745,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "857470281336543408" + "version": "0.26.54.24096", + "templateHash": "5827467280453778347" }, "name": "API Management Service APIs", "description": "This module deploys an API Management Service API.", @@ -1007,8 +1007,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "5383521143080449228" + "version": "0.26.54.24096", + "templateHash": "11734266416309377949" }, "name": "API Management Service APIs Policies", "description": "This module deploys an API Management Service API Policy.", @@ -1153,8 +1153,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4002198465184356188" + "version": "0.26.54.24096", + "templateHash": "14411287735172753559" }, "name": "API Management Service API Version Sets", "description": "This module deploys an API Management Service API Version Set.", @@ -1269,8 +1269,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "6703063831636643162" + "version": "0.26.54.24096", + "templateHash": "505882801529152233" }, "name": "API Management Service Authorization Servers", "description": "This module deploys an API Management Service Authorization Server.", @@ -1512,8 +1512,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16587888030936573636" + "version": "0.26.54.24096", + "templateHash": "5914852504306173482" }, "name": "API Management Service Backends", "description": "This module deploys an API Management Service Backend.", @@ -1696,8 +1696,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "1295772952565058470" + "version": "0.26.54.24096", + "templateHash": "5452536693649070190" }, "name": "API Management Service Caches", "description": "This module deploys an API Management Service Cache.", @@ -1831,8 +1831,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17146377320278316178" + "version": "0.26.54.24096", + "templateHash": "6944159515007886666" }, "name": "API Management Service Identity Providers", "description": "This module deploys an API Management Service Identity Provider.", @@ -2018,8 +2018,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "5043439748386656207" + "version": "0.26.54.24096", + "templateHash": "17256518550792037410" }, "name": "API Management Service Named Values", "description": "This module deploys an API Management Service Named Value.", @@ -2159,8 +2159,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14726250901514511689" + "version": "0.26.54.24096", + "templateHash": "6528716876560144579" }, "name": "API Management Service Portal Settings", "description": "This module deploys an API Management Service Portal Setting.", @@ -2256,8 +2256,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3643398305472631880" + "version": "0.26.54.24096", + "templateHash": "12407621079025229005" }, "name": "API Management Service Policies", "description": "This module deploys an API Management Service Policy.", @@ -2372,8 +2372,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "10657321045680066427" + "version": "0.26.54.24096", + "templateHash": "2407987626180908324" }, "name": "API Management Service Products", "description": "This module deploys an API Management Service Product.", @@ -2494,8 +2494,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2508310027677163402" + "version": "0.26.54.24096", + "templateHash": "2440306385645798125" }, "name": "API Management Service Products APIs", "description": "This module deploys an API Management Service Product API.", @@ -2584,8 +2584,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14996351450231036018" + "version": "0.26.54.24096", + "templateHash": "7056381119937736015" }, "name": "API Management Service Products Groups", "description": "This module deploys an API Management Service Product Group.", @@ -2741,8 +2741,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16952030877948084799" + "version": "0.26.54.24096", + "templateHash": "12071485798846786639" }, "name": "API Management Service Subscriptions", "description": "This module deploys an API Management Service Subscription.", diff --git a/avm/res/app/container-app/main.bicep b/avm/res/app/container-app/main.bicep index 381bf515f6..6692443b0c 100644 --- a/avm/res/app/container-app/main.bicep +++ b/avm/res/app/container-app/main.bicep @@ -114,7 +114,7 @@ var secretList = !empty(secrets) ? secrets.secureList : [] 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) + type: (managedIdentities.?systemAssigned ?? false) ? (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : 'None') userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null } : null diff --git a/avm/res/app/container-app/main.json b/avm/res/app/container-app/main.json index 65f3d6c5bb..feda04977c 100644 --- a/avm/res/app/container-app/main.json +++ b/avm/res/app/container-app/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "6631896891995690305" + "version": "0.26.54.24096", + "templateHash": "18118452764225711784" }, "name": "Container Apps", "description": "This module deploys a Container App.", @@ -361,7 +361,7 @@ "variables": { "secretList": "[if(not(empty(parameters('secrets'))), parameters('secrets').secureList, createArray())]", "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())]", + "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": { "ContainerApp Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ad2dd5fb-cd4b-4fd4-a9b6-4fed3630980b')]", "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", diff --git a/avm/res/batch/batch-account/main.bicep b/avm/res/batch/batch-account/main.bicep index 8d7cbddb36..738927d0da 100644 --- a/avm/res/batch/batch-account/main.bicep +++ b/avm/res/batch/batch-account/main.bicep @@ -76,7 +76,7 @@ param managedIdentities managedIdentitiesType 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) ? 'SystemAssigned' : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null) + type: (managedIdentities.?systemAssigned ?? false) ? 'SystemAssigned' : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : 'None') userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null } : null diff --git a/avm/res/batch/batch-account/main.json b/avm/res/batch/batch-account/main.json index 925fe85130..8cee3097cc 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.25.53.49325", - "templateHash": "11102129881431176996" + "version": "0.26.54.24096", + "templateHash": "1015260763007678357" }, "name": "Batch Accounts", "description": "This module deploys a Batch Account.", @@ -657,7 +657,7 @@ } ], "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', null())), '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()), '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')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", diff --git a/avm/res/cache/redis/main.bicep b/avm/res/cache/redis/main.bicep index 38ffba3aab..4c8b7ec5b2 100644 --- a/avm/res/cache/redis/main.bicep +++ b/avm/res/cache/redis/main.bicep @@ -110,7 +110,7 @@ var availabilityZones = skuName == 'Premium' ? zoneRedundant ? !empty(zones) ? z 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) + type: (managedIdentities.?systemAssigned ?? false) ? (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : 'None') userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null } : null diff --git a/avm/res/cache/redis/main.json b/avm/res/cache/redis/main.json index 9a90df4cd8..ea843325ec 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.25.53.49325", - "templateHash": "798005420934456091" + "version": "0.26.54.24096", + "templateHash": "4340647324706279011" }, "name": "Redis Cache", "description": "This module deploys a Redis Cache.", @@ -629,7 +629,7 @@ "variables": { "availabilityZones": "[if(equals(parameters('skuName'), 'Premium'), if(parameters('zoneRedundant'), if(not(empty(parameters('zones'))), parameters('zones'), pickZones('Microsoft.Cache', 'redis', parameters('location'), 3)), createArray()), createArray())]", "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())]", + "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": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", diff --git a/avm/res/data-factory/factory/main.bicep b/avm/res/data-factory/factory/main.bicep index 02a736accc..d2eafaf5e5 100644 --- a/avm/res/data-factory/factory/main.bicep +++ b/avm/res/data-factory/factory/main.bicep @@ -82,7 +82,7 @@ param enableTelemetry bool = true 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) + type: (managedIdentities.?systemAssigned ?? false) ? (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : 'None') userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null } : null diff --git a/avm/res/data-factory/factory/main.json b/avm/res/data-factory/factory/main.json index 309d4053b9..5b911b63c3 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.26.54.24096", - "templateHash": "18305717161046402755" + "templateHash": "7527516376989418326" }, "name": "Data Factories", "description": "This module deploys a Data Factory.", @@ -633,7 +633,7 @@ }, "variables": { "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())]", + "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": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Data Factory Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '673868aa-7521-48a0-acc6-0f60742d39f5')]", diff --git a/avm/res/databricks/access-connector/main.bicep b/avm/res/databricks/access-connector/main.bicep index b749e46a04..734b8347a9 100644 --- a/avm/res/databricks/access-connector/main.bicep +++ b/avm/res/databricks/access-connector/main.bicep @@ -26,7 +26,7 @@ param enableTelemetry bool = true 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) + type: (managedIdentities.?systemAssigned ?? false) ? (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : 'None') userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null } : { type: 'None' diff --git a/avm/res/databricks/access-connector/main.json b/avm/res/databricks/access-connector/main.json index d6eadf1fcd..6e4b21fc5a 100644 --- a/avm/res/databricks/access-connector/main.json +++ b/avm/res/databricks/access-connector/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11132516876546852007" + "version": "0.26.54.24096", + "templateHash": "4967596969090590192" }, "name": "Azure Databricks Access Connectors", "description": "This module deploys an Azure Databricks Access Connector.", @@ -177,7 +177,7 @@ }, "variables": { "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())), createObject('type', 'None'))]", + "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')]", 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 235a431d3c..25a0d55485 100644 --- a/avm/res/db-for-postgre-sql/flexible-server/main.bicep +++ b/avm/res/db-for-postgre-sql/flexible-server/main.bicep @@ -158,7 +158,7 @@ param diagnosticSettings diagnosticSettingType 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: !empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null + type: !empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : 'None' userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null } : null 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 3282c25ad9..9044c56c4c 100644 --- a/avm/res/db-for-postgre-sql/flexible-server/main.json +++ b/avm/res/db-for-postgre-sql/flexible-server/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14524458345533599390" + "version": "0.26.54.24096", + "templateHash": "13621373926800305772" }, "name": "DBforPostgreSQL Flexible Servers", "description": "This module deploys a DBforPostgreSQL Flexible Server.", @@ -546,7 +546,7 @@ }, "variables": { "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())]", + "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', 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')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", @@ -756,8 +756,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "12415562574078248070" + "version": "0.26.54.24096", + "templateHash": "9123565269712158909" }, "name": "DBforPostgreSQL Flexible Server Databases", "description": "This module deploys a DBforPostgreSQL Flexible Server Database.", @@ -864,8 +864,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "12878552829645985725" + "version": "0.26.54.24096", + "templateHash": "4295272529604037098" }, "name": "DBforPostgreSQL Flexible Server Firewall Rules", "description": "This module deploys a DBforPostgreSQL Flexible Server Firewall Rule.", @@ -969,8 +969,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "13489282175455188314" + "version": "0.26.54.24096", + "templateHash": "15593908401685608166" }, "name": "DBforPostgreSQL Flexible Server Configurations", "description": "This module deploys a DBforPostgreSQL Flexible Server Configuration.", @@ -1079,8 +1079,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14998758936357296642" + "version": "0.26.54.24096", + "templateHash": "4962117704341008645" }, "name": "DBforPostgreSQL Flexible Server Administrators", "description": "This module deploys a DBforPostgreSQL Flexible Server Administrator.", diff --git a/avm/res/logic/workflow/main.bicep b/avm/res/logic/workflow/main.bicep index 709b83da75..8c216c1f07 100644 --- a/avm/res/logic/workflow/main.bicep +++ b/avm/res/logic/workflow/main.bicep @@ -82,7 +82,7 @@ param workflowTriggers object? 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) ? 'SystemAssigned' : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null) + type: (managedIdentities.?systemAssigned ?? false) ? 'SystemAssigned' : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : 'None') userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null } : null diff --git a/avm/res/logic/workflow/main.json b/avm/res/logic/workflow/main.json index 54957dd91a..a4a47a39f7 100644 --- a/avm/res/logic/workflow/main.json +++ b/avm/res/logic/workflow/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2286082865500450205" + "version": "0.26.54.24096", + "templateHash": "11157035480094020050" }, "name": "Logic Apps (Workflows)", "description": "This module deploys a Logic App (Workflow).", @@ -429,7 +429,7 @@ }, "variables": { "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', null())), '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()), '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')]", "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", 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 d53bccd3e7..c8c55afaa8 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 @@ -15,8 +15,8 @@ This module deploys an Azure NetApp Files Capacity Pool. | 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.NetApp/netAppAccounts/capacityPools` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/netAppAccounts/capacityPools) | -| `Microsoft.NetApp/netAppAccounts/capacityPools/volumes` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/netAppAccounts/capacityPools/volumes) | +| `Microsoft.NetApp/netAppAccounts/capacityPools` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2022-11-01/netAppAccounts/capacityPools) | +| `Microsoft.NetApp/netAppAccounts/capacityPools/volumes` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2022-11-01/netAppAccounts/capacityPools/volumes) | ## Parameters 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 0d146bf069..9a7443b188 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.25.53.49325", - "templateHash": "9701673230796867736" + "version": "0.26.54.24096", + "templateHash": "9491401922190427460" }, "name": "Azure NetApp Files Capacity Pools", "description": "This module deploys an Azure NetApp Files Capacity Pool.", @@ -273,8 +273,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "8808262417279983135" + "version": "0.26.54.24096", + "templateHash": "9587584861242006945" }, "name": "Azure NetApp Files Capacity Pool Volumes", "description": "This module deploys an Azure NetApp Files Capacity Pool Volume.", 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 4b934d6584..f498296bd2 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 @@ -15,7 +15,7 @@ This module deploys an Azure NetApp Files Capacity Pool Volume. | 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.NetApp/netAppAccounts/capacityPools/volumes` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/netAppAccounts/capacityPools/volumes) | +| `Microsoft.NetApp/netAppAccounts/capacityPools/volumes` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2022-11-01/netAppAccounts/capacityPools/volumes) | ## Parameters 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 358a2f7d6e..864cc09926 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.25.53.49325", - "templateHash": "8808262417279983135" + "version": "0.26.54.24096", + "templateHash": "9587584861242006945" }, "name": "Azure NetApp Files Capacity Pool Volumes", "description": "This module deploys an Azure NetApp Files Capacity Pool Volume.", diff --git a/avm/res/net-app/net-app-account/main.bicep b/avm/res/net-app/net-app-account/main.bicep index 35913dd2f2..66f9aa5b34 100644 --- a/avm/res/net-app/net-app-account/main.bicep +++ b/avm/res/net-app/net-app-account/main.bicep @@ -59,7 +59,7 @@ var activeDirectoryConnectionProperties = [ 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: !empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null + type: !empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : 'None' userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null } : null diff --git a/avm/res/net-app/net-app-account/main.json b/avm/res/net-app/net-app-account/main.json index 4cc3dd1b91..0a8f097fdb 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.25.53.49325", - "templateHash": "18391773655889763585" + "version": "0.26.54.24096", + "templateHash": "5838174533550571700" }, "name": "Azure NetApp Files", "description": "This module deploys an Azure NetApp File.", @@ -228,7 +228,7 @@ } ], "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())]", + "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', 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')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", @@ -348,8 +348,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "9701673230796867736" + "version": "0.26.54.24096", + "templateHash": "9491401922190427460" }, "name": "Azure NetApp Files Capacity Pools", "description": "This module deploys an Azure NetApp Files Capacity Pool.", @@ -616,8 +616,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "8808262417279983135" + "version": "0.26.54.24096", + "templateHash": "9587584861242006945" }, "name": "Azure NetApp Files Capacity Pool Volumes", "description": "This module deploys an Azure NetApp Files Capacity Pool Volume.", diff --git a/avm/res/storage/storage-account/main.bicep b/avm/res/storage/storage-account/main.bicep index f8cc6f0c9a..f95b1f1f23 100644 --- a/avm/res/storage/storage-account/main.bicep +++ b/avm/res/storage/storage-account/main.bicep @@ -180,7 +180,7 @@ var supportsFileService = kind == 'FileStorage' || kind == 'StorageV2' || kind = 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) + type: (managedIdentities.?systemAssigned ?? false) ? (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : 'None') userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null } : null diff --git a/avm/res/storage/storage-account/main.json b/avm/res/storage/storage-account/main.json index 0180a0b231..d4a1fa422f 100644 --- a/avm/res/storage/storage-account/main.json +++ b/avm/res/storage/storage-account/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16595339509600711048" + "version": "0.26.54.24096", + "templateHash": "13878793352750035767" }, "name": "Storage Accounts", "description": "This module deploys a Storage Account.", @@ -820,7 +820,7 @@ "supportsBlobService": "[or(or(or(equals(parameters('kind'), 'BlockBlobStorage'), equals(parameters('kind'), 'BlobStorage')), equals(parameters('kind'), 'StorageV2')), equals(parameters('kind'), 'Storage'))]", "supportsFileService": "[or(or(equals(parameters('kind'), 'FileStorage'), equals(parameters('kind'), 'StorageV2')), equals(parameters('kind'), 'Storage'))]", "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())]", + "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": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", @@ -1691,8 +1691,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "774635646248081518" + "version": "0.26.54.24096", + "templateHash": "14052382142427178929" }, "name": "Storage Account Management Policies", "description": "This module deploys a Storage Account Management Policy.", @@ -1801,8 +1801,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17117452291389534361" + "version": "0.26.54.24096", + "templateHash": "3388645117303533667" }, "name": "Storage Account Local Users", "description": "This module deploys a Storage Account Local User, which is used for SFTP authentication.", @@ -2019,8 +2019,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4746835745355709536" + "version": "0.26.54.24096", + "templateHash": "12175020972967228537" }, "name": "Storage Account blob Services", "description": "This module deploys a Storage Account Blob Service.", @@ -2417,8 +2417,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11351273351916968732" + "version": "0.26.54.24096", + "templateHash": "3297137219061666309" }, "name": "Storage Account Blob Containers", "description": "This module deploys a Storage Account Blob Container.", @@ -2686,8 +2686,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "10329548264889228160" + "version": "0.26.54.24096", + "templateHash": "2429139364933838439" }, "name": "Storage Account Blob Container Immutability Policies", "description": "This module deploys a Storage Account Blob Container Immutability Policy.", @@ -2865,8 +2865,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "5288106279947156711" + "version": "0.26.54.24096", + "templateHash": "13860799899517512764" }, "name": "Storage Account File Share Services", "description": "This module deploys a Storage Account File Share Service.", @@ -3146,8 +3146,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2026482374148202879" + "version": "0.26.54.24096", + "templateHash": "18405917853511220559" }, "name": "Storage Account File Shares", "description": "This module deploys a Storage Account File Share.", @@ -3346,8 +3346,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "15595600813016932186" + "version": "0.26.54.24096", + "templateHash": "16221226236637657314" } }, "parameters": { @@ -3615,8 +3615,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14446905482734328346" + "version": "0.26.54.24096", + "templateHash": "13677013226831946461" }, "name": "Storage Account Queue Services", "description": "This module deploys a Storage Account Queue Service.", @@ -3860,8 +3860,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "12411465246702614738" + "version": "0.26.54.24096", + "templateHash": "17219066722763101567" }, "name": "Storage Account Queues", "description": "This module deploys a Storage Account Queue.", @@ -4117,8 +4117,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14471460242481977546" + "version": "0.26.54.24096", + "templateHash": "17373442840517371502" }, "name": "Storage Account Table Services", "description": "This module deploys a Storage Account Table Service.", @@ -4359,8 +4359,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "8824223095963877860" + "version": "0.26.54.24096", + "templateHash": "10226619499666007193" }, "name": "Storage Account Table", "description": "This module deploys a Storage Account Table.", From c2f625047e5d865e735534ef8aa6bb32ee7d79d8 Mon Sep 17 00:00:00 2001 From: Bryan <117635118+bryansan-msft@users.noreply.github.com> Date: Tue, 26 Mar 2024 09:02:57 +0100 Subject: [PATCH 64/73] feat: public network restricted access and new account level flags (#1407) ## Description - Added a way to automatically add connection strings and key to a key vault the consumer specified. - Closes #632 - Added possibility to restrict to IPs, CIDRS and subnets. - Closes #1255 - Closes #1370 - Allow possibility to disable metadata write with access keys. - Closes #1233 - Allow enablement of multi write/master regions. - Closes #1232 - Removed the use of 'Range' partition key. Impossible to make it work and there is not any documentation stating that this is even possible to use/deploy. Not even through the portal or az cli. - Closes #1234 - Changed default kind of database from Parse to GlobalDocumentDb. Parse is deprecated as per this issue https://github.com/Azure/azure-cli/issues/16583#issuecomment-1270246876 - Merged tests that can be together without conflicts and significant increase of deployment duration. - Added an empty SQL database to most tests to force SQL API accounts to test common properties. - Calculate failover location for accounts that only have one region as the customer currently must repeat the location twice because it was required. - Changed test region from eastus to eastasia as it started to have capacity constraints as well - In some cases analytical storage ttl cannot be set at all. Not even to 0. So I moved to an union ro remove it completely when it is 0. PD: @Azure/avm-core-team-technical-bicep Can we make the PSRules less restrictive or their errors and fixes clearer? I have just wasted 2 hours because I had an error saying my param didn't have a description, but they did. It turned out it was a missing "." at the end of the description. I had to dig into the PSRule, take the regex and go to a regex playground to discover what was happening. Not very developer friendly I would say ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.document-db.database-account](https://github.com/bryansan-msft/fork-bicep-registry-modules/actions/workflows/avm.res.document-db.database-account.yml/badge.svg)](https://github.com/bryansan-msft/fork-bicep-registry-modules/actions/workflows/avm.res.document-db.database-account.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [ ] Azure Verified Module updates: - [ ] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [x] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [x] The bug was found by the module author, and no one has opened an issue to report it yet. - [x] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [x] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [x] I have run `Set-AVMModule` locally to generate the supporting module files. - [x] My corresponding pipelines / checks run clean and green without any errors or warnings --- .../document-db/database-account/README.md | 1429 +++++++---------- .../gremlin-database/graph/main.json | 4 +- .../gremlin-database/main.json | 8 +- .../document-db/database-account/main.bicep | 228 ++- .../document-db/database-account/main.json | 517 ++++-- .../modules/secrets-key-vault.bicep | 21 + .../mongodb-database/collection/main.json | 4 +- .../mongodb-database/main.json | 8 +- .../sql-database/container/main.bicep | 35 +- .../sql-database/container/main.json | 34 +- .../database-account/sql-database/main.json | 38 +- .../tests/e2e/analytical/main.test.bicep | 11 +- .../main.test.bicep | 11 +- .../tests/e2e/continousBckup/main.test.bicep | 59 - .../tests/e2e/defaults/main.test.bicep | 11 +- .../tests/e2e/disableLocal/main.test.bicep | 57 - .../tests/e2e/gremlindb/main.test.bicep | 2 +- .../tests/e2e/kvSecrets/dependencies.bicep | 21 + .../{systemMi => kvSecrets}/main.test.bicep | 31 +- .../dependencies.bicep | 4 +- .../main.test.bicep | 31 +- .../tests/e2e/mongodb/main.test.bicep | 2 +- .../dependencies.bicep | 0 .../main.test.bicep | 21 +- .../tests/e2e/periodicBckup/main.test.bicep | 61 - .../tests/e2e/plain/main.test.bicep | 78 +- .../publicRestrictedAccess/dependencies.bicep | 35 + .../publicRestrictedAccess/main.test.bicep | 78 + .../tests/e2e/sqldb/main.test.bicep | 2 +- .../tests/e2e/userMi/dependencies.bicep | 16 - .../tests/e2e/waf-aligned/dependencies.bicep | 44 - .../tests/e2e/waf-aligned/main.test.bicep | 50 +- .../tests/e2e/zoneRedundant/main.test.bicep | 52 - .../document-db/database-account/version.json | 2 +- 34 files changed, 1497 insertions(+), 1508 deletions(-) create mode 100644 avm/res/document-db/database-account/modules/secrets-key-vault.bicep rename avm/res/document-db/database-account/tests/e2e/{consistency => boundedConsistency}/main.test.bicep (89%) delete mode 100644 avm/res/document-db/database-account/tests/e2e/continousBckup/main.test.bicep delete mode 100644 avm/res/document-db/database-account/tests/e2e/disableLocal/main.test.bicep create mode 100644 avm/res/document-db/database-account/tests/e2e/kvSecrets/dependencies.bicep rename avm/res/document-db/database-account/tests/e2e/{systemMi => kvSecrets}/main.test.bicep (64%) rename avm/res/document-db/database-account/tests/e2e/{plain => managedIdentity}/dependencies.bicep (91%) rename avm/res/document-db/database-account/tests/e2e/{userMi => managedIdentity}/main.test.bicep (70%) rename avm/res/document-db/database-account/tests/e2e/{autoFailoverOff => multiRegion}/dependencies.bicep (100%) rename avm/res/document-db/database-account/tests/e2e/{autoFailoverOff => multiRegion}/main.test.bicep (77%) delete mode 100644 avm/res/document-db/database-account/tests/e2e/periodicBckup/main.test.bicep create mode 100644 avm/res/document-db/database-account/tests/e2e/publicRestrictedAccess/dependencies.bicep create mode 100644 avm/res/document-db/database-account/tests/e2e/publicRestrictedAccess/main.test.bicep delete mode 100644 avm/res/document-db/database-account/tests/e2e/userMi/dependencies.bicep delete mode 100644 avm/res/document-db/database-account/tests/e2e/zoneRedundant/main.test.bicep diff --git a/avm/res/document-db/database-account/README.md b/avm/res/document-db/database-account/README.md index 48ecea6820..3c6471cc2a 100644 --- a/avm/res/document-db/database-account/README.md +++ b/avm/res/document-db/database-account/README.md @@ -25,6 +25,7 @@ This module deploys a DocumentDB Database Account. | `Microsoft.DocumentDB/databaseAccounts/sqlDatabases` | [2023-04-15](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2023-04-15/databaseAccounts/sqlDatabases) | | `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.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` | [2022-07-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2022-07-01/vaults/secrets) | | `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) | @@ -37,20 +38,17 @@ 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/document-db/database-account:`. - [Using analytical storage](#example-1-using-analytical-storage) -- [Without automatic failover](#example-2-without-automatic-failover) -- [Using bounded consistency](#example-3-using-bounded-consistency) -- [Enabling continous backups](#example-4-enabling-continous-backups) -- [Using only defaults](#example-5-using-only-defaults) -- [Disabling local authentication. i.e. access keys](#example-6-disabling-local-authentication-ie-access-keys) -- [Gremlin Database](#example-7-gremlin-database) -- [Mongo Database](#example-8-mongo-database) -- [Using periodic backups](#example-9-using-periodic-backups) -- [Plain](#example-10-plain) +- [Using bounded consistency](#example-2-using-bounded-consistency) +- [Using only defaults](#example-3-using-only-defaults) +- [Gremlin Database](#example-4-gremlin-database) +- [Deploying with a key vault reference to save secrets](#example-5-deploying-with-a-key-vault-reference-to-save-secrets) +- [Deploying with Managed identities](#example-6-deploying-with-managed-identities) +- [Mongo Database](#example-7-mongo-database) +- [Deploying multiple regions](#example-8-deploying-multiple-regions) +- [Plain](#example-9-plain) +- [Public network restricted access with ACL](#example-10-public-network-restricted-access-with-acl) - [SQL Database](#example-11-sql-database) -- [Deploying with a System-Assigned Identity](#example-12-deploying-with-a-system-assigned-identity) -- [Deploying with a User-Assigned Identity](#example-13-deploying-with-a-user-assigned-identity) -- [WAF-aligned](#example-14-waf-aligned) -- [Using zone redundant regions](#example-15-using-zone-redundant-regions) +- [WAF-aligned](#example-12-waf-aligned) ### Example 1: _Using analytical storage_ @@ -66,20 +64,13 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: name: 'databaseAccountDeployment' params: { // Required parameters - locations: [ - { - failoverPriority: 0 - isZoneRedundant: false - locationName: '' - } - ] name: 'analytical' // Non-required parameters enableAnalyticalStorage: true location: '' sqlDatabases: [ { - name: 'empty-database' + name: 'no-containers-specified' } ] } @@ -99,15 +90,6 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: "contentVersion": "1.0.0.0", "parameters": { // Required parameters - "locations": { - "value": [ - { - "failoverPriority": 0, - "isZoneRedundant": false, - "locationName": "" - } - ] - }, "name": { "value": "analytical" }, @@ -121,97 +103,7 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: "sqlDatabases": { "value": [ { - "name": "empty-database" - } - ] - } - } -} -``` - - -

- -### Example 2: _Without automatic failover_ - -This instance deploys the module disabling automatic failover. - - -

- -via Bicep module - -```bicep -module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: 'databaseAccountDeployment' - params: { - // Required parameters - locations: [ - { - failoverPriority: 0 - isZoneRedundant: false - locationName: '' - } - { - failoverPriority: 1 - isZoneRedundant: false - locationName: '' - } - ] - name: 'auto-failover-off' - // Non-required parameters - automaticFailover: false - location: '' - sqlDatabases: [ - { - name: 'empty-database' - } - ] - } -} -``` - -
-

- -

- -via JSON Parameter file - -```json -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - // Required parameters - "locations": { - "value": [ - { - "failoverPriority": 0, - "isZoneRedundant": false, - "locationName": "" - }, - { - "failoverPriority": 1, - "isZoneRedundant": false, - "locationName": "" - } - ] - }, - "name": { - "value": "auto-failover-off" - }, - // Non-required parameters - "automaticFailover": { - "value": false - }, - "location": { - "value": "" - }, - "sqlDatabases": { - "value": [ - { - "name": "empty-database" + "name": "no-containers-specified" } ] } @@ -222,7 +114,7 @@ module databaseAccount 'br/public:avm/res/document-db/database-account:

-### Example 3: _Using bounded consistency_ +### Example 2: _Using bounded consistency_ This instance deploys the module specifying a default consistency level. @@ -236,13 +128,6 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: name: 'databaseAccountDeployment' params: { // Required parameters - locations: [ - { - failoverPriority: 0 - isZoneRedundant: false - locationName: '' - } - ] name: 'bounded' // Non-required parameters defaultConsistencyLevel: 'BoundedStaleness' @@ -251,7 +136,7 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: maxStalenessPrefix: 200000 sqlDatabases: [ { - name: 'empty-database' + name: 'no-containers-specified' } ] } @@ -271,15 +156,6 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: "contentVersion": "1.0.0.0", "parameters": { // Required parameters - "locations": { - "value": [ - { - "failoverPriority": 0, - "isZoneRedundant": false, - "locationName": "" - } - ] - }, "name": { "value": "bounded" }, @@ -299,91 +175,7 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: "sqlDatabases": { "value": [ { - "name": "empty-database" - } - ] - } - } -} -``` - - -

- -### Example 4: _Enabling continous backups_ - -This instance deploys the module enabling continous backups. - - -

- -via Bicep module - -```bicep -module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: 'databaseAccountDeployment' - params: { - // Required parameters - locations: [ - { - failoverPriority: 0 - isZoneRedundant: false - locationName: '' - } - ] - name: 'continous-bckup' - // Non-required parameters - backupPolicyContinuousTier: 'Continuous7Days' - backupPolicyType: 'Continuous' - location: '' - sqlDatabases: [ - { - name: 'empty-database' - } - ] - } -} -``` - -
-

- -

- -via JSON Parameter file - -```json -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - // Required parameters - "locations": { - "value": [ - { - "failoverPriority": 0, - "isZoneRedundant": false, - "locationName": "" - } - ] - }, - "name": { - "value": "continous-bckup" - }, - // Non-required parameters - "backupPolicyContinuousTier": { - "value": "Continuous7Days" - }, - "backupPolicyType": { - "value": "Continuous" - }, - "location": { - "value": "" - }, - "sqlDatabases": { - "value": [ - { - "name": "empty-database" + "name": "no-containers-specified" } ] } @@ -394,7 +186,7 @@ module databaseAccount 'br/public:avm/res/document-db/database-account:

-### Example 5: _Using only defaults_ +### Example 3: _Using only defaults_ This instance deploys the module with the minimum set of required parameters. @@ -408,13 +200,6 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: name: 'databaseAccountDeployment' params: { // Required parameters - locations: [ - { - failoverPriority: 0 - isZoneRedundant: false - locationName: '' - } - ] name: 'dddamin001' // Non-required parameters location: '' @@ -435,15 +220,6 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: "contentVersion": "1.0.0.0", "parameters": { // Required parameters - "locations": { - "value": [ - { - "failoverPriority": 0, - "isZoneRedundant": false, - "locationName": "" - } - ] - }, "name": { "value": "dddamin001" }, @@ -458,87 +234,7 @@ module databaseAccount 'br/public:avm/res/document-db/database-account:

-### Example 6: _Disabling local authentication. i.e. access keys_ - -This instance deploys the module disabling local authentication. - - -

- -via Bicep module - -```bicep -module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: 'databaseAccountDeployment' - params: { - // Required parameters - locations: [ - { - failoverPriority: 0 - isZoneRedundant: false - locationName: '' - } - ] - name: 'local-auth-off' - // Non-required parameters - disableLocalAuth: true - location: '' - sqlDatabases: [ - { - name: 'empty-database' - } - ] - } -} -``` - -
-

- -

- -via JSON Parameter file - -```json -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - // Required parameters - "locations": { - "value": [ - { - "failoverPriority": 0, - "isZoneRedundant": false, - "locationName": "" - } - ] - }, - "name": { - "value": "local-auth-off" - }, - // Non-required parameters - "disableLocalAuth": { - "value": true - }, - "location": { - "value": "" - }, - "sqlDatabases": { - "value": [ - { - "name": "empty-database" - } - ] - } - } -} -``` - -
-

- -### Example 7: _Gremlin Database_ +### Example 4: _Gremlin Database_ This instance deploys the module with a Gremlin Database. @@ -552,18 +248,6 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: name: 'databaseAccountDeployment' params: { // Required parameters - locations: [ - { - failoverPriority: 0 - isZoneRedundant: false - locationName: '' - } - { - failoverPriority: 1 - isZoneRedundant: false - locationName: '' - } - ] name: 'dddagrm002' // Non-required parameters capabilitiesToAdd: [ @@ -633,6 +317,18 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: } ] location: '' + locations: [ + { + failoverPriority: 0 + isZoneRedundant: false + locationName: '' + } + { + failoverPriority: 1 + isZoneRedundant: false + locationName: '' + } + ] managedIdentities: { systemAssigned: true } @@ -675,20 +371,6 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: "contentVersion": "1.0.0.0", "parameters": { // Required parameters - "locations": { - "value": [ - { - "failoverPriority": 0, - "isZoneRedundant": false, - "locationName": "" - }, - { - "failoverPriority": 1, - "isZoneRedundant": false, - "locationName": "" - } - ] - }, "name": { "value": "dddagrm002" }, @@ -768,9 +450,186 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: "location": { "value": "" }, + "locations": { + "value": [ + { + "failoverPriority": 0, + "isZoneRedundant": false, + "locationName": "" + }, + { + "failoverPriority": 1, + "isZoneRedundant": false, + "locationName": "" + } + ] + }, + "managedIdentities": { + "value": { + "systemAssigned": true + } + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + + +

+ +### Example 5: _Deploying with a key vault reference to save secrets_ + +This instance deploys the module saving all its secrets in a key vault. + + +

+ +via Bicep module + +```bicep +module databaseAccount 'br/public:avm/res/document-db/database-account:' = { + name: 'databaseAccountDeployment' + params: { + // Required parameters + name: 'kv-ref' + // Non-required parameters + location: '' + secretsKeyVault: { + keyVaultName: '' + primaryReadonlyConnectionStringSecretName: 'custom-secret-name' + } + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "kv-ref" + }, + // Non-required parameters + "location": { + "value": "" + }, + "secretsKeyVault": { + "value": { + "keyVaultName": "", + "primaryReadonlyConnectionStringSecretName": "custom-secret-name" + } + } + } +} +``` + +
+

+ +### Example 6: _Deploying with Managed identities_ + +This instance deploys the module with an system and user assigned managed identity. + + +

+ +via Bicep module + +```bicep +module databaseAccount 'br/public:avm/res/document-db/database-account:' = { + name: 'databaseAccountDeployment' + params: { + // Required parameters + name: 'user-mi' + // Non-required parameters + location: '' + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + '' + ] + } + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "user-mi" + }, + // Non-required parameters + "location": { + "value": "" + }, "managedIdentities": { "value": { - "systemAssigned": true + "systemAssigned": true, + "userAssignedResourceIds": [ + "" + ] } }, "roleAssignments": { @@ -791,13 +650,6 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: "roleDefinitionIdOrName": "" } ] - }, - "tags": { - "value": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } } } } @@ -806,7 +658,7 @@ module databaseAccount 'br/public:avm/res/document-db/database-account:

-### Example 8: _Mongo Database_ +### Example 7: _Mongo Database_ This instance deploys the module with a Mongo Database. @@ -820,18 +672,6 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: name: 'databaseAccountDeployment' params: { // Required parameters - locations: [ - { - failoverPriority: 0 - isZoneRedundant: false - locationName: '' - } - { - failoverPriority: 1 - isZoneRedundant: false - locationName: '' - } - ] name: 'dddamng001' // Non-required parameters diagnosticSettings: [ @@ -849,6 +689,18 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: } ] location: '' + locations: [ + { + failoverPriority: 0 + isZoneRedundant: false + locationName: '' + } + { + failoverPriority: 1 + isZoneRedundant: false + locationName: '' + } + ] managedIdentities: { systemAssigned: true } @@ -1077,20 +929,6 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: "contentVersion": "1.0.0.0", "parameters": { // Required parameters - "locations": { - "value": [ - { - "failoverPriority": 0, - "isZoneRedundant": false, - "locationName": "" - }, - { - "failoverPriority": 1, - "isZoneRedundant": false, - "locationName": "" - } - ] - }, "name": { "value": "dddamng001" }, @@ -1114,6 +952,20 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: "location": { "value": "" }, + "locations": { + "value": [ + { + "failoverPriority": 0, + "isZoneRedundant": false, + "locationName": "" + }, + { + "failoverPriority": 1, + "isZoneRedundant": false, + "locationName": "" + } + ] + }, "managedIdentities": { "value": { "systemAssigned": true @@ -1340,9 +1192,9 @@ module databaseAccount 'br/public:avm/res/document-db/database-account:

-### Example 9: _Using periodic backups_ +### Example 8: _Deploying multiple regions_ -This instance deploys the module enabling periodic backups. +This instance deploys the module in multiple regions with configs specific of multi region scenarios.

@@ -1354,23 +1206,30 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: name: 'databaseAccountDeployment' params: { // Required parameters - locations: [ - { - failoverPriority: 0 - isZoneRedundant: false - locationName: '' - } - ] - name: 'periodic-bckup' + name: 'multi-region' // Non-required parameters + automaticFailover: false backupIntervalInMinutes: 300 backupPolicyType: 'Periodic' backupRetentionIntervalInHours: 16 backupStorageRedundancy: 'Zone' + enableMultipleWriteLocations: true location: '' + locations: [ + { + failoverPriority: 0 + isZoneRedundant: true + locationName: '' + } + { + failoverPriority: 1 + isZoneRedundant: true + locationName: '' + } + ] sqlDatabases: [ { - name: 'empty-database' + name: 'no-containers-specified' } ] } @@ -1390,19 +1249,13 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: "contentVersion": "1.0.0.0", "parameters": { // Required parameters - "locations": { - "value": [ - { - "failoverPriority": 0, - "isZoneRedundant": false, - "locationName": "" - } - ] - }, "name": { - "value": "periodic-bckup" + "value": "multi-region" }, // Non-required parameters + "automaticFailover": { + "value": false + }, "backupIntervalInMinutes": { "value": 300 }, @@ -1415,13 +1268,30 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: "backupStorageRedundancy": { "value": "Zone" }, + "enableMultipleWriteLocations": { + "value": true + }, "location": { "value": "" }, + "locations": { + "value": [ + { + "failoverPriority": 0, + "isZoneRedundant": true, + "locationName": "" + }, + { + "failoverPriority": 1, + "isZoneRedundant": true, + "locationName": "" + } + ] + }, "sqlDatabases": { "value": [ { - "name": "empty-database" + "name": "no-containers-specified" } ] } @@ -1432,7 +1302,7 @@ module databaseAccount 'br/public:avm/res/document-db/database-account:

-### Example 10: _Plain_ +### Example 9: _Plain_ This instance deploys the module without a Database. @@ -1446,6 +1316,14 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: name: 'databaseAccountDeployment' params: { // Required parameters + name: 'dddapln001' + // Non-required parameters + backupPolicyContinuousTier: 'Continuous7Days' + backupPolicyType: 'Continuous' + defaultConsistencyLevel: 'ConsistentPrefix' + disableKeyBasedMetadataWriteAccess: true + disableLocalAuth: true + location: '' locations: [ { failoverPriority: 0 @@ -1453,49 +1331,11 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: locationName: '' } ] - name: 'dddapln001' - // Non-required parameters - diagnosticSettings: [ - { - eventHubAuthorizationRuleResourceId: '' - eventHubName: '' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - name: 'customSetting' - storageAccountResourceId: '' - workspaceResourceId: '' - } - ] - location: '' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - roleAssignments: [ - { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: 'Owner' - } - { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - } + sqlDatabases: [ { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: '' + name: 'no-containers-specified' } ] - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } } } ``` @@ -1513,6 +1353,28 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: "contentVersion": "1.0.0.0", "parameters": { // Required parameters + "name": { + "value": "dddapln001" + }, + // Non-required parameters + "backupPolicyContinuousTier": { + "value": "Continuous7Days" + }, + "backupPolicyType": { + "value": "Continuous" + }, + "defaultConsistencyLevel": { + "value": "ConsistentPrefix" + }, + "disableKeyBasedMetadataWriteAccess": { + "value": true + }, + "disableLocalAuth": { + "value": true + }, + "location": { + "value": "" + }, "locations": { "value": [ { @@ -1522,60 +1384,100 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: } ] }, - "name": { - "value": "dddapln001" - }, - // Non-required parameters - "diagnosticSettings": { + "sqlDatabases": { "value": [ { - "eventHubAuthorizationRuleResourceId": "", - "eventHubName": "", - "metricCategories": [ - { - "category": "AllMetrics" - } - ], - "name": "customSetting", - "storageAccountResourceId": "", - "workspaceResourceId": "" + "name": "no-containers-specified" + } + ] + } + } +} +``` + + +

+ +### Example 10: _Public network restricted access with ACL_ + +This instance deploys the module with public network access enabled but restricted to IPs, CIDRS or subnets. + + +

+ +via Bicep module + +```bicep +module databaseAccount 'br/public:avm/res/document-db/database-account:' = { + name: 'databaseAccountDeployment' + params: { + // Required parameters + name: 'dddapres001' + // Non-required parameters + location: '' + networkRestrictions: { + ipRules: [ + '79.0.0.0' + '80.0.0.0' + ] + networkAclBypass: 'AzureServices' + publicNetworkAccess: 'Enabled' + virtualNetworkRules: [ + { + subnetResourceId: '' } ] + } + sqlDatabases: [ + { + name: 'no-containers-specified' + } + ] + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "dddapres001" }, + // Non-required parameters "location": { "value": "" }, - "lock": { + "networkRestrictions": { "value": { - "kind": "CanNotDelete", - "name": "myCustomLockName" + "ipRules": [ + "79.0.0.0", + "80.0.0.0" + ], + "networkAclBypass": "AzureServices", + "publicNetworkAccess": "Enabled", + "virtualNetworkRules": [ + { + "subnetResourceId": "" + } + ] } }, - "roleAssignments": { + "sqlDatabases": { "value": [ { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "Owner" - }, - { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" - }, - { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "" + "name": "no-containers-specified" } ] - }, - "tags": { - "value": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } } } } @@ -1598,6 +1500,10 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: name: 'databaseAccountDeployment' params: { // Required parameters + name: 'dddasql001' + // Non-required parameters + enableAnalyticalStorage: true + location: '' locations: [ { failoverPriority: 0 @@ -1605,10 +1511,6 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: locationName: '' } ] - name: 'dddasql001' - // Non-required parameters - enableAnalyticalStorage: true - location: '' sqlDatabases: [ { containers: [ @@ -1868,15 +1770,6 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: "contentVersion": "1.0.0.0", "parameters": { // Required parameters - "locations": { - "value": [ - { - "failoverPriority": 0, - "isZoneRedundant": false, - "locationName": "" - } - ] - }, "name": { "value": "dddasql001" }, @@ -1887,6 +1780,15 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: "location": { "value": "" }, + "locations": { + "value": [ + { + "failoverPriority": 0, + "isZoneRedundant": false, + "locationName": "" + } + ] + }, "sqlDatabases": { "value": [ { @@ -2138,155 +2040,7 @@ module databaseAccount 'br/public:avm/res/document-db/database-account:

-### Example 12: _Deploying with a System-Assigned Identity_ - -This instance deploys the module with an assigned system assigned managed identity. - - -

- -via Bicep module - -```bicep -module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: 'databaseAccountDeployment' - params: { - // Required parameters - locations: [ - { - failoverPriority: 0 - isZoneRedundant: false - locationName: '' - } - ] - name: 'system-mi' - // Non-required parameters - location: '' - managedIdentities: { - systemAssigned: true - } - } -} -``` - -
-

- -

- -via JSON Parameter file - -```json -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - // Required parameters - "locations": { - "value": [ - { - "failoverPriority": 0, - "isZoneRedundant": false, - "locationName": "" - } - ] - }, - "name": { - "value": "system-mi" - }, - // Non-required parameters - "location": { - "value": "" - }, - "managedIdentities": { - "value": { - "systemAssigned": true - } - } - } -} -``` - -
-

- -### Example 13: _Deploying with a User-Assigned Identity_ - -This instance deploys the module with an assigned user assigned managed identity. - - -

- -via Bicep module - -```bicep -module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: 'databaseAccountDeployment' - params: { - // Required parameters - locations: [ - { - failoverPriority: 0 - isZoneRedundant: false - locationName: '' - } - ] - name: 'user-mi' - // Non-required parameters - location: '' - managedIdentities: { - userAssignedResourceIds: [ - '' - ] - } - } -} -``` - -
-

- -

- -via JSON Parameter file - -```json -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - // Required parameters - "locations": { - "value": [ - { - "failoverPriority": 0, - "isZoneRedundant": false, - "locationName": "" - } - ] - }, - "name": { - "value": "user-mi" - }, - // Non-required parameters - "location": { - "value": "" - }, - "managedIdentities": { - "value": { - "userAssignedResourceIds": [ - "" - ] - } - } - } -} -``` - -
-

- -### Example 14: _WAF-aligned_ +### Example 12: _WAF-aligned_ This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework. @@ -2300,18 +2054,6 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: name: 'databaseAccountDeployment' params: { // Required parameters - locations: [ - { - failoverPriority: 0 - isZoneRedundant: false - locationName: '' - } - { - failoverPriority: 1 - isZoneRedundant: false - locationName: '' - } - ] name: 'dddawaf001' // Non-required parameters diagnosticSettings: [ @@ -2322,7 +2064,12 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: workspaceResourceId: '' } ] + disableKeyBasedMetadataWriteAccess: true location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } privateEndpoints: [ { privateDnsZoneResourceIds: [ @@ -2336,42 +2083,19 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: Role: 'DeploymentValidation' } } - ] - sqlDatabases: [ - { - containers: [ - { - analyticalStorageTtl: 0 - conflictResolutionPolicy: { - conflictResolutionPath: '/myCustomId' - mode: 'LastWriterWins' - } - defaultTtl: 1000 - indexingPolicy: { - automatic: true - } - kind: 'Hash' - name: 'container-001' - paths: [ - '/myPartitionKey' - ] - throughput: 600 - uniqueKeyPolicyKeys: [ - { - paths: [ - '/firstName' - ] - } - { - paths: [ - '/lastName' - ] - } + ] + sqlDatabases: [ + { + containers: [ + { + kind: 'Hash' + name: 'container-001' + paths: [ + '/myPartitionKey1' ] } ] name: 'sql-dddawaf-001' - throughput: 1000 } ] tags: { @@ -2396,20 +2120,6 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: "contentVersion": "1.0.0.0", "parameters": { // Required parameters - "locations": { - "value": [ - { - "failoverPriority": 0, - "isZoneRedundant": false, - "locationName": "" - }, - { - "failoverPriority": 1, - "isZoneRedundant": false, - "locationName": "" - } - ] - }, "name": { "value": "dddawaf001" }, @@ -2424,9 +2134,18 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: } ] }, + "disableKeyBasedMetadataWriteAccess": { + "value": true + }, "location": { "value": "" }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, "privateEndpoints": { "value": [ { @@ -2448,37 +2167,14 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: { "containers": [ { - "analyticalStorageTtl": 0, - "conflictResolutionPolicy": { - "conflictResolutionPath": "/myCustomId", - "mode": "LastWriterWins" - }, - "defaultTtl": 1000, - "indexingPolicy": { - "automatic": true - }, "kind": "Hash", "name": "container-001", "paths": [ - "/myPartitionKey" - ], - "throughput": 600, - "uniqueKeyPolicyKeys": [ - { - "paths": [ - "/firstName" - ] - }, - { - "paths": [ - "/lastName" - ] - } + "/myPartitionKey1" ] } ], - "name": "sql-dddawaf-001", - "throughput": 1000 + "name": "sql-dddawaf-001" } ] }, @@ -2496,70 +2192,6 @@ module databaseAccount 'br/public:avm/res/document-db/database-account:

-### Example 15: _Using zone redundant regions_ - -This instance deploys the module enabling multiple zone redundant in multiple regions. - - -

- -via Bicep module - -```bicep -module databaseAccount 'br/public:avm/res/document-db/database-account:' = { - name: 'databaseAccountDeployment' - params: { - // Required parameters - locations: [ - { - failoverPriority: 0 - isZoneRedundant: true - locationName: '' - } - ] - name: 'zone-redundant' - // Non-required parameters - location: '' - } -} -``` - -
-

- -

- -via JSON Parameter file - -```json -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - // Required parameters - "locations": { - "value": [ - { - "failoverPriority": 0, - "isZoneRedundant": true, - "locationName": "" - } - ] - }, - "name": { - "value": "zone-redundant" - }, - // Non-required parameters - "location": { - "value": "" - } - } -} -``` - -
-

- ## Parameters @@ -2567,7 +2199,6 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: | Parameter | Type | Description | | :-- | :-- | :-- | -| [`locations`](#parameter-locations) | array | Locations enabled for the Cosmos DB account. | | [`name`](#parameter-name) | string | Name of the Database Account. | **Optional parameters** @@ -2577,37 +2208,35 @@ module databaseAccount 'br/public:avm/res/document-db/database-account: | [`automaticFailover`](#parameter-automaticfailover) | bool | Default to true. Enable automatic failover for regions. | | [`backupIntervalInMinutes`](#parameter-backupintervalinminutes) | int | Default to 240. An integer representing the interval in minutes between two backups. Only applies to periodic backup type. | | [`backupPolicyContinuousTier`](#parameter-backuppolicycontinuoustier) | string | Default to Continuous30Days. Configuration values for continuous mode backup. | -| [`backupPolicyType`](#parameter-backuppolicytype) | string | Default to Continuous. Describes the mode of backups. | +| [`backupPolicyType`](#parameter-backuppolicytype) | string | Default to Continuous. Describes the mode of backups. Periodic backup must be used if multiple write locations are used. | | [`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. | | [`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 | Default to false. Disable write operations on metadata resources (databases, containers, throughput) via account keys. | | [`disableLocalAuth`](#parameter-disablelocalauth) | bool | Default to false. Opt-out of local authentication and ensure only MSI and AAD can be used exclusively for authentication. | | [`enableAnalyticalStorage`](#parameter-enableanalyticalstorage) | bool | Default to false. Flag to indicate whether to enable storage analytics. | | [`enableFreeTier`](#parameter-enablefreetier) | bool | Default to false. Flag to indicate whether Free Tier is enabled. | +| [`enableMultipleWriteLocations`](#parameter-enablemultiplewritelocations) | bool | Default to false. Enables the account to write in multiple locations. Periodic backup must be used if enabled. | | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`gremlinDatabases`](#parameter-gremlindatabases) | array | Gremlin Databases configurations. | | [`location`](#parameter-location) | string | Default to current resource group scope location. Location for all resources. | +| [`locations`](#parameter-locations) | array | Default to the location where the account is deployed. Locations enabled for the Cosmos DB account. | | [`lock`](#parameter-lock) | object | The lock settings of the service. | | [`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. | | [`mongodbDatabases`](#parameter-mongodbdatabases) | array | MongoDB Databases configurations. | +| [`networkRestrictions`](#parameter-networkrestrictions) | object | The network configuration of this module. | | [`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'. | +| [`secretsKeyVault`](#parameter-secretskeyvault) | object | Key vault reference and secret settings to add the connection strings and keys generated by the cosmosdb account. | | [`serverVersion`](#parameter-serverversion) | string | Default to 4.2. Specifies the MongoDB server version to use. | | [`sqlDatabases`](#parameter-sqldatabases) | array | SQL Databases configurations. | | [`tags`](#parameter-tags) | object | Tags of the Database Account resource. | -### Parameter: `locations` - -Locations enabled for the Cosmos DB account. - -- Required: Yes -- Type: array - ### Parameter: `name` Name of the Database Account. @@ -2648,7 +2277,7 @@ Default to Continuous30Days. Configuration values for continuous mode backup. ### Parameter: `backupPolicyType` -Default to Continuous. Describes the mode of backups. +Default to Continuous. Describes the mode of backups. Periodic backup must be used if multiple write locations are used. - Required: No - Type: string @@ -2882,6 +2511,14 @@ Resource ID of the diagnostic log analytics workspace. For security reasons, it - Required: No - Type: string +### Parameter: `disableKeyBasedMetadataWriteAccess` + +Default to false. Disable write operations on metadata resources (databases, containers, throughput) via account keys. + +- Required: No +- Type: bool +- Default: `False` + ### Parameter: `disableLocalAuth` Default to false. Opt-out of local authentication and ensure only MSI and AAD can be used exclusively for authentication. @@ -2906,6 +2543,14 @@ Default to false. Flag to indicate whether Free Tier is enabled. - Type: bool - Default: `False` +### Parameter: `enableMultipleWriteLocations` + +Default to false. Enables the account to write in multiple locations. Periodic backup must be used if enabled. + +- Required: No +- Type: bool +- Default: `False` + ### Parameter: `enableTelemetry` Enable/Disable usage telemetry for module. @@ -2930,6 +2575,14 @@ Default to current resource group scope location. Location for all resources. - Type: string - Default: `[resourceGroup().location]` +### Parameter: `locations` + +Default to the location where the account is deployed. Locations enabled for the Cosmos DB account. + +- Required: No +- Type: array +- Default: `[]` + ### Parameter: `lock` The lock settings of the service. @@ -3018,6 +2671,77 @@ MongoDB Databases configurations. - Type: array - Default: `[]` +### Parameter: `networkRestrictions` + +The network configuration of this module. + +- Required: No +- Type: object + +**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". + +- Required: Yes +- Type: array + +### Parameter: `networkRestrictions.networkAclBypass` + +Default to AzureServices. Specifies the network ACL bypass for Azure services. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'AzureServices' + 'None' + ] + ``` + +### Parameter: `networkRestrictions.publicNetworkAccess` + +Default to Enabled. Whether requests from Public Network are allowed. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + +### 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. @@ -3434,6 +3158,103 @@ The principal type of the assigned principal ID. ] ``` +### Parameter: `secretsKeyVault` + +Key vault reference and secret settings to add the connection strings and keys generated by the cosmosdb account. + +- Required: No +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`keyVaultName`](#parameter-secretskeyvaultkeyvaultname) | string | The key vault name where to store the keys and connection strings generated by the modules. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`primaryReadonlyConnectionStringSecretName`](#parameter-secretskeyvaultprimaryreadonlyconnectionstringsecretname) | string | Default to Primary-Readonly-ConnectionString. The primary readonly connection string secret name to create. | +| [`primaryReadOnlyKeySecretName`](#parameter-secretskeyvaultprimaryreadonlykeysecretname) | string | Default to Primary-Readonly-Key. The primary readonly key secret name to create. | +| [`primaryWriteConnectionStringSecretName`](#parameter-secretskeyvaultprimarywriteconnectionstringsecretname) | string | Default to Primary-Write-ConnectionString. The primary write connection string secret name to create. | +| [`primaryWriteKeySecretName`](#parameter-secretskeyvaultprimarywritekeysecretname) | string | Default to Primary-Write-Key. The primary write key secret name to create. | +| [`resourceGroupName`](#parameter-secretskeyvaultresourcegroupname) | string | Default to the resource group where this account is. The resource group name where the key vault is. | +| [`secondaryReadonlyConnectionStringSecretName`](#parameter-secretskeyvaultsecondaryreadonlyconnectionstringsecretname) | string | Default to Secondary-Readonly-ConnectionString. The primary readonly connection string secret name to create. | +| [`secondaryReadonlyKeySecretName`](#parameter-secretskeyvaultsecondaryreadonlykeysecretname) | string | Default to Secondary-Readonly-Key. The primary readonly key secret name to create. | +| [`secondaryWriteConnectionStringSecretName`](#parameter-secretskeyvaultsecondarywriteconnectionstringsecretname) | string | Default to Secondary-Write-ConnectionString. The primary write connection string secret name to create. | +| [`secondaryWriteKeySecretName`](#parameter-secretskeyvaultsecondarywritekeysecretname) | string | Default to Secondary-Write-Key. The primary write key secret name to create. | + +### Parameter: `secretsKeyVault.keyVaultName` + +The key vault name where to store the keys and connection strings generated by the modules. + +- Required: Yes +- Type: string + +### Parameter: `secretsKeyVault.primaryReadonlyConnectionStringSecretName` + +Default to Primary-Readonly-ConnectionString. The primary readonly connection string secret name to create. + +- Required: No +- Type: string + +### Parameter: `secretsKeyVault.primaryReadOnlyKeySecretName` + +Default to Primary-Readonly-Key. The primary readonly key secret name to create. + +- Required: No +- Type: string + +### Parameter: `secretsKeyVault.primaryWriteConnectionStringSecretName` + +Default to Primary-Write-ConnectionString. The primary write connection string secret name to create. + +- Required: No +- Type: string + +### Parameter: `secretsKeyVault.primaryWriteKeySecretName` + +Default to Primary-Write-Key. The primary write key secret name to create. + +- Required: No +- Type: string + +### Parameter: `secretsKeyVault.resourceGroupName` + +Default to the resource group where this account is. The resource group name where the key vault is. + +- Required: No +- Type: string + +### Parameter: `secretsKeyVault.secondaryReadonlyConnectionStringSecretName` + +Default to Secondary-Readonly-ConnectionString. The primary readonly connection string secret name to create. + +- Required: No +- Type: string + +### Parameter: `secretsKeyVault.secondaryReadonlyKeySecretName` + +Default to Secondary-Readonly-Key. The primary readonly key secret name to create. + +- Required: No +- Type: string + +### Parameter: `secretsKeyVault.secondaryWriteConnectionStringSecretName` + +Default to Secondary-Write-ConnectionString. The primary write connection string secret name to create. + +- Required: No +- Type: string + +### Parameter: `secretsKeyVault.secondaryWriteKeySecretName` + +Default to Secondary-Write-Key. The primary write key secret name to create. + +- Required: No +- Type: string + ### Parameter: `serverVersion` Default to 4.2. Specifies the MongoDB server version to use. 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 531189986d..1779026f4f 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.25.53.49325", - "templateHash": "4078462189838201163" + "version": "0.26.54.24096", + "templateHash": "2823004405398378621" }, "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 1ff6b48baa..c3cd9ee8c7 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.25.53.49325", - "templateHash": "5227237801347888732" + "version": "0.26.54.24096", + "templateHash": "13414524346849431368" }, "name": "DocumentDB Database Account Gremlin Databases", "description": "This module deploys a Gremlin Database within a CosmosDB Account.", @@ -109,8 +109,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4078462189838201163" + "version": "0.26.54.24096", + "templateHash": "2823004405398378621" }, "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 6e5e62b83c..6df84d2c31 100644 --- a/avm/res/document-db/database-account/main.bicep +++ b/avm/res/document-db/database-account/main.bicep @@ -20,8 +20,8 @@ param managedIdentities managedIdentitiesType ]) param databaseAccountOfferType string = 'Standard' -@description('Required. Locations enabled for the Cosmos DB account.') -param locations failoverLocations[] +@description('Optional. Default to the location where the account is deployed. Locations enabled for the Cosmos DB account.') +param locations failoverLocationsType[] = [] @allowed([ 'Eventual' @@ -45,6 +45,12 @@ param automaticFailover bool = true @description('Optional. Default to false. Flag to indicate whether Free Tier is enabled.') param enableFreeTier bool = false +@description('Optional. Default to false. Enables the account to write in multiple locations. Periodic backup must be used if enabled.') +param enableMultipleWriteLocations bool = false + +@description('Optional. Default to false. Disable write operations on metadata resources (databases, containers, throughput) via account keys.') +param disableKeyBasedMetadataWriteAccess bool = false + @minValue(1) @maxValue(2147483647) @description('Optional. Default to 100000. Max stale requests. Required for BoundedStaleness. Valid ranges, Single Region: 10 to 1000000. Multi Region: 100000 to 1000000.') @@ -65,7 +71,7 @@ param maxIntervalInSeconds int = 300 param serverVersion string = '4.2' @description('Optional. SQL Databases configurations.') -param sqlDatabases sqlDatabase[] = [] +param sqlDatabases sqlDatabaseType[] = [] @description('Optional. MongoDB Databases configurations.') param mongodbDatabases array = [] @@ -100,7 +106,7 @@ param capabilitiesToAdd string[] = [] 'Periodic' 'Continuous' ]) -@description('Optional. Default to Continuous. Describes the mode of backups.') +@description('Optional. Default to Continuous. Describes the mode of backups. Periodic backup must be used if multiple write locations are used.') param backupPolicyType string = 'Continuous' @allowed([ @@ -131,6 +137,12 @@ param backupStorageRedundancy string = 'Local' @description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') param privateEndpoints privateEndpointType +@description('Optional. Key vault reference and secret settings to add the connection strings and keys generated by the cosmosdb account.') +param secretsKeyVault secretsKeyVaultType? + +@description('Optional. The network configuration of this module.') +param networkRestrictions networkRestrictionsType? + 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) ? { @@ -158,13 +170,19 @@ var consistencyPolicy = { } } -var databaseAccount_locations = [for location in locations: { - failoverPriority: location.failoverPriority - isZoneRedundant: location.isZoneRedundant - locationName: location.locationName +var defaultFailoverLocation = [ { + failoverPriority: 0 + locationName: location + isZoneRedundant: true + } ] + +var databaseAccount_locations = [for failoverLocation in locations: { + failoverPriority: failoverLocation.failoverPriority + locationName: failoverLocation.locationName + isZoneRedundant: failoverLocation.?isZoneRedundant ?? true }] -var kind = !empty(sqlDatabases) || !empty(gremlinDatabases) ? 'GlobalDocumentDB' : (!empty(mongodbDatabases) ? 'MongoDB' : 'Parse') +var kind = !empty(sqlDatabases) || !empty(gremlinDatabases) ? 'GlobalDocumentDB' : (!empty(mongodbDatabases) ? 'MongoDB' : 'GlobalDocumentDB') var capabilities = [for capability in capabilitiesToAdd: { name: capability @@ -184,12 +202,29 @@ var backupPolicy = backupPolicyType == 'Continuous' ? { } } +var ipRules = [for i in (networkRestrictions.?ipRules ?? []): { + ipAddressOrRange: i +}] + +var virtualNetworkRules = [for vnet in (networkRestrictions.?virtualNetworkRules ?? []): { + id: vnet.subnetResourceId + ignoreMissingVnetServiceEndpoint: false +}] + var databaseAccount_properties = union({ databaseAccountOfferType: databaseAccountOfferType }, ((!empty(sqlDatabases) || !empty(mongodbDatabases) || !empty(gremlinDatabases)) ? { // Common properties consistencyPolicy: consistencyPolicy[defaultConsistencyLevel] - locations: databaseAccount_locations + enableMultipleWriteLocations: enableMultipleWriteLocations + locations: empty(databaseAccount_locations) ? defaultFailoverLocation : databaseAccount_locations + + ipRules: ipRules + virtualNetworkRules: virtualNetworkRules + networkAclBypass: networkRestrictions.?networkAclBypass ?? 'AzureServices' + publicNetworkAccess: networkRestrictions.?publicNetworkAccess ?? 'Enabled' + isVirtualNetworkFilterEnabled: !empty(ipRules) || !empty(virtualNetworkRules) + capabilities: capabilities enableFreeTier: enableFreeTier backupPolicy: backupPolicy @@ -198,6 +233,7 @@ var databaseAccount_properties = union({ } : {}), (!empty(sqlDatabases) ? { // SQLDB properties disableLocalAuth: disableLocalAuth + disableKeyBasedMetadataWriteAccess: disableKeyBasedMetadataWriteAccess } : {}), (!empty(mongodbDatabases) ? { // MongoDb properties apiProperties: { @@ -367,6 +403,49 @@ module databaseAccount_privateEndpoints 'br/public:avm/res/network/private-endpo } }] +module keyVault 'modules/secrets-key-vault.bicep' = if (secretsKeyVault != null) { + name: '${uniqueString(deployment().name, location)}-secrets-kv' + scope: resourceGroup(secretsKeyVault.?resourceGroupName ?? resourceGroup().name) + params: { + keyVaultName: secretsKeyVault!.keyVaultName + + keySecrets: [ + { + secretName: secretsKeyVault.?primaryWriteKeySecretName ?? 'Primary-Write-Key' + secretValue: databaseAccount.listKeys().primaryMasterKey + } + { + secretName: secretsKeyVault.?primaryReadOnlyKeySecretName ?? 'Primary-Readonly-Key' + secretValue: databaseAccount.listKeys().primaryReadonlyMasterKey + } + { + secretName: secretsKeyVault.?primaryWriteConnectionStringSecretName ?? 'Primary-Write-ConnectionString' + secretValue: databaseAccount.listConnectionStrings().connectionStrings[0].connectionString + } + { + secretName: secretsKeyVault.?primaryReadonlyConnectionStringSecretName ?? 'Primary-Readonly-ConnectionString' + secretValue: databaseAccount.listConnectionStrings().connectionStrings[2].connectionString + } + { + secretName: secretsKeyVault.?secondaryWriteKeySecretName ?? 'Secondary-Write-Key' + secretValue: databaseAccount.listKeys().secondaryMasterKey + } + { + secretName: secretsKeyVault.?secondaryReadonlyKeySecretName ?? 'Secondary-Readonly-Key' + secretValue: databaseAccount.listKeys().secondaryReadonlyMasterKey + } + { + secretName: secretsKeyVault.?secondaryWriteConnectionStringSecretName ?? 'Secondary-Write-ConnectionString' + secretValue: databaseAccount.listConnectionStrings().connectionStrings[1].connectionString + } + { + secretName: secretsKeyVault.?secondaryReadonlyConnectionStringSecretName ?? 'Secondary-Readonly-ConnectionString' + secretValue: databaseAccount.listConnectionStrings().connectionStrings[3].connectionString + } + ] + } +} + @description('The name of the database account.') output name string = databaseAccount.name @@ -541,18 +620,18 @@ type diagnosticSettingType = { marketplacePartnerResourceId: string? }[]? -type failoverLocations = { +type failoverLocationsType = { @description('Required. The failover priority of the region. A failover priority of 0 indicates a write region. The maximum value for a failover priority = (total number of regions - 1). Failover priority values must be unique for each of the regions in which the database account exists.') failoverPriority: int - @description('Required. Flag to indicate whether or not this region is an AvailabilityZone region') - isZoneRedundant: bool + @description('Optional. Default to true. Flag to indicate whether or not this region is an AvailabilityZone region') + isZoneRedundant: bool? @description('Required. The name of the region.') locationName: string } -type sqlDatabase = { +type sqlDatabaseType = { @description('Required. Name of the SQL database .') name: string @@ -563,54 +642,101 @@ type sqlDatabase = { autoscaleSettingsMaxThroughput: int? @description('Optional. Array of containers to deploy in the SQL database.') - containers: sqlDatabaseContainer[]? + containers: { + @description('Required. Name of the container.') + name: string + + @maxLength(3) + @minLength(1) + @description('Required. List of paths using which data within the container can be partitioned. For kind=MultiHash it can be up to 3. For anything else it needs to be exactly 1.') + paths: string[] + + @description('Optional. Default to 0. Indicates how long data should be retained in the analytical store, for a container. Analytical store is enabled when ATTL is set with a value other than 0. If the value is set to -1, the analytical store retains all historical data, irrespective of the retention of the data in the transactional store.') + analyticalStorageTtl: int? + + @maxValue(1000000) + @description('Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to null, then autoscale will be disabled.') + autoscaleSettingsMaxThroughput: int? + + @description('Optional. The conflict resolution policy for the container. Conflicts and conflict resolution policies are applicable if the Azure Cosmos DB account is configured with multiple write regions.') + conflictResolutionPolicy: { + @description('Required if mode=LastWriterWins. The conflict resolution path in the case of LastWriterWins mode.') + conflictResolutionPath: string? + + @description('Required if mode=Custom. The procedure to resolve conflicts in the case of custom mode.') + conflictResolutionProcedure: string? + + @description('Required. Indicates the conflict resolution mode.') + mode: ('Custom' | 'LastWriterWins') + }? + + @maxValue(2147483647) + @minValue(-1) + @description('Optional. Default to -1. Default time to live (in seconds). With Time to Live or TTL, Azure Cosmos DB provides the ability to delete items automatically from a container after a certain time period. If the value is set to "-1", it is equal to infinity, and items don\'t expire by default.') + defaultTtl: int? + + @description('Optional. Indexing policy of the container.') + indexingPolicy: object? + + @description('Optional. Default to Hash. Indicates the kind of algorithm used for partitioning.') + kind: ('Hash' | 'MultiHash')? + + @description('Optional. Default to 400. Request Units per second. Will be ignored if autoscaleSettingsMaxThroughput is used.') + throughput: int? + + @description('Optional. The unique key policy configuration containing a list of unique keys that enforces uniqueness constraint on documents in the collection in the Azure Cosmos DB service.') + uniqueKeyPolicyKeys: { + @description('List of paths must be unique for each document in the Azure Cosmos DB service') + paths: string[] + }[]? + }[]? } -type sqlDatabaseContainer = { - @description('Required. Name of the container.') - name: string +type secretsKeyVaultType = { + @description('Required. The key vault name where to store the keys and connection strings generated by the modules.') + keyVaultName: string - @maxLength(3) - @minLength(1) - @description('Required. List of paths using which data within the container can be partitioned. For kind=MultiHash it can be up to 3. For anything else it needs to be exactly 1.') - paths: string[] + @description('Optional. Default to the resource group where this account is. The resource group name where the key vault is.') + resourceGroupName: string? - @description('Optional. Default to 0. Indicates how long data should be retained in the analytical store, for a container. Analytical store is enabled when ATTL is set with a value other than 0. If the value is set to -1, the analytical store retains all historical data, irrespective of the retention of the data in the transactional store.') - analyticalStorageTtl: int? + @description('Optional. Default to Primary-Write-Key. The primary write key secret name to create.') + primaryWriteKeySecretName: string? - @maxValue(1000000) - @description('Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to null, then autoscale will be disabled.') - autoscaleSettingsMaxThroughput: int? + @description('Optional. Default to Primary-Readonly-Key. The primary readonly key secret name to create.') + primaryReadOnlyKeySecretName: string? - @description('Optional. The conflict resolution policy for the container. Conflicts and conflict resolution policies are applicable if the Azure Cosmos DB account is configured with multiple write regions.') - conflictResolutionPolicy: { - @description('Required if mode=LastWriterWins. The conflict resolution path in the case of LastWriterWins mode.') - conflictResolutionPath: string? + @description('Optional. Default to Primary-Write-ConnectionString. The primary write connection string secret name to create.') + primaryWriteConnectionStringSecretName: string? - @description('Required if mode=Custom. The procedure to resolve conflicts in the case of custom mode.') - conflictResolutionProcedure: string? + @description('Optional. Default to Primary-Readonly-ConnectionString. The primary readonly connection string secret name to create.') + primaryReadonlyConnectionStringSecretName: string? - @description('Required. Indicates the conflict resolution mode.') - mode: ('Custom' | 'LastWriterWins') - }? + @description('Optional. Default to Secondary-Write-Key. The primary write key secret name to create.') + secondaryWriteKeySecretName: string? - @maxValue(2147483647) - @minValue(-1) - @description('Optional. Default to -1. Default time to live (in seconds). With Time to Live or TTL, Azure Cosmos DB provides the ability to delete items automatically from a container after a certain time period. If the value is set to "-1", it is equal to infinity, and items don\'t expire by default.') - defaultTtl: int? + @description('Optional. Default to Secondary-Readonly-Key. The primary readonly key secret name to create.') + secondaryReadonlyKeySecretName: string? - @description('Optional. Indexing policy of the container.') - indexingPolicy: object? + @description('Optional. Default to Secondary-Write-ConnectionString. The primary write connection string secret name to create.') + secondaryWriteConnectionStringSecretName: string? - @description('Optional. Default to Hash. Indicates the kind of algorithm used for partitioning.') - kind: ('Hash' | 'MultiHash' | 'Range')? + @description('Optional. Default to Secondary-Readonly-ConnectionString. The primary readonly connection string secret name to create.') + secondaryReadonlyConnectionStringSecretName: string? +} - @description('Optional. Default to 400. Request Units per second. Will be ignored if autoscaleSettingsMaxThroughput is used.') - throughput: int? +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".') + ipRules: string[] - @description('Optional. The unique key policy configuration containing a list of unique keys that enforces uniqueness constraint on documents in the collection in the Azure Cosmos DB service.') - uniqueKeyPolicyKeys: { - @description('List of paths must be unique for each document in the Azure Cosmos DB service') - paths: string[] - }[]? + @description('Optional. Default to AzureServices. Specifies the network ACL bypass for Azure services.') + networkAclBypass: ('AzureServices' | 'None')? + + @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..') + 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 fbe677ed99..c2d0432835 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.25.53.49325", - "templateHash": "8733005894926174924" + "version": "0.26.54.24096", + "templateHash": "1074920414166959578" }, "name": "DocumentDB Database Accounts", "description": "This module deploys a DocumentDB Database Account.", @@ -429,7 +429,7 @@ }, "nullable": true }, - "failoverLocations": { + "failoverLocationsType": { "type": "object", "properties": { "failoverPriority": { @@ -440,8 +440,9 @@ }, "isZoneRedundant": { "type": "bool", + "nullable": true, "metadata": { - "description": "Required. Flag to indicate whether or not this region is an AvailabilityZone region" + "description": "Optional. Default to true. Flag to indicate whether or not this region is an AvailabilityZone region" } }, "locationName": { @@ -452,7 +453,7 @@ } } }, - "sqlDatabase": { + "sqlDatabaseType": { "type": "object", "properties": { "name": { @@ -478,7 +479,129 @@ "containers": { "type": "array", "items": { - "$ref": "#/definitions/sqlDatabaseContainer" + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the container." + } + }, + "paths": { + "type": "array", + "items": { + "type": "string" + }, + "minLength": 1, + "maxLength": 3, + "metadata": { + "description": "Required. List of paths using which data within the container can be partitioned. For kind=MultiHash it can be up to 3. For anything else it needs to be exactly 1." + } + }, + "analyticalStorageTtl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Default to 0. Indicates how long data should be retained in the analytical store, for a container. Analytical store is enabled when ATTL is set with a value other than 0. If the value is set to -1, the analytical store retains all historical data, irrespective of the retention of the data in the transactional store." + } + }, + "autoscaleSettingsMaxThroughput": { + "type": "int", + "nullable": true, + "maxValue": 1000000, + "metadata": { + "description": "Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to null, then autoscale will be disabled." + } + }, + "conflictResolutionPolicy": { + "type": "object", + "properties": { + "conflictResolutionPath": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Required if mode=LastWriterWins. The conflict resolution path in the case of LastWriterWins mode." + } + }, + "conflictResolutionProcedure": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Required if mode=Custom. The procedure to resolve conflicts in the case of custom mode." + } + }, + "mode": { + "type": "string", + "allowedValues": [ + "Custom", + "LastWriterWins" + ], + "metadata": { + "description": "Required. Indicates the conflict resolution mode." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The conflict resolution policy for the container. Conflicts and conflict resolution policies are applicable if the Azure Cosmos DB account is configured with multiple write regions." + } + }, + "defaultTtl": { + "type": "int", + "nullable": true, + "minValue": -1, + "maxValue": 2147483647, + "metadata": { + "description": "Optional. Default to -1. Default time to live (in seconds). With Time to Live or TTL, Azure Cosmos DB provides the ability to delete items automatically from a container after a certain time period. If the value is set to \"-1\", it is equal to infinity, and items don't expire by default." + } + }, + "indexingPolicy": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Indexing policy of the container." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "Hash", + "MultiHash" + ], + "nullable": true, + "metadata": { + "description": "Optional. Default to Hash. Indicates the kind of algorithm used for partitioning." + } + }, + "throughput": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Default to 400. Request Units per second. Will be ignored if autoscaleSettingsMaxThroughput is used." + } + }, + "uniqueKeyPolicyKeys": { + "type": "array", + "items": { + "type": "object", + "properties": { + "paths": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "List of paths must be unique for each document in the Azure Cosmos DB service" + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The unique key policy configuration containing a list of unique keys that enforces uniqueness constraint on documents in the collection in the Azure Cosmos DB service." + } + } + } }, "nullable": true, "metadata": { @@ -487,128 +610,129 @@ } } }, - "sqlDatabaseContainer": { + "secretsKeyVaultType": { "type": "object", "properties": { - "name": { + "keyVaultName": { "type": "string", "metadata": { - "description": "Required. Name of the container." + "description": "Required. The key vault name where to store the keys and connection strings generated by the modules." } }, - "paths": { - "type": "array", - "items": { - "type": "string" - }, - "minLength": 1, - "maxLength": 3, + "resourceGroupName": { + "type": "string", + "nullable": true, "metadata": { - "description": "Required. List of paths using which data within the container can be partitioned. For kind=MultiHash it can be up to 3. For anything else it needs to be exactly 1." + "description": "Optional. Default to the resource group where this account is. The resource group name where the key vault is." } }, - "analyticalStorageTtl": { - "type": "int", + "primaryWriteKeySecretName": { + "type": "string", "nullable": true, "metadata": { - "description": "Optional. Default to 0. Indicates how long data should be retained in the analytical store, for a container. Analytical store is enabled when ATTL is set with a value other than 0. If the value is set to -1, the analytical store retains all historical data, irrespective of the retention of the data in the transactional store." + "description": "Optional. Default to Primary-Write-Key. The primary write key secret name to create." } }, - "autoscaleSettingsMaxThroughput": { - "type": "int", + "primaryReadOnlyKeySecretName": { + "type": "string", "nullable": true, - "maxValue": 1000000, "metadata": { - "description": "Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to null, then autoscale will be disabled." + "description": "Optional. Default to Primary-Readonly-Key. The primary readonly key secret name to create." } }, - "conflictResolutionPolicy": { - "type": "object", - "properties": { - "conflictResolutionPath": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Required if mode=LastWriterWins. The conflict resolution path in the case of LastWriterWins mode." - } - }, - "conflictResolutionProcedure": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Required if mode=Custom. The procedure to resolve conflicts in the case of custom mode." - } - }, - "mode": { - "type": "string", - "allowedValues": [ - "Custom", - "LastWriterWins" - ], - "metadata": { - "description": "Required. Indicates the conflict resolution mode." - } - } - }, + "primaryWriteConnectionStringSecretName": { + "type": "string", "nullable": true, "metadata": { - "description": "Optional. The conflict resolution policy for the container. Conflicts and conflict resolution policies are applicable if the Azure Cosmos DB account is configured with multiple write regions." + "description": "Optional. Default to Primary-Write-ConnectionString. The primary write connection string secret name to create." } }, - "defaultTtl": { - "type": "int", + "primaryReadonlyConnectionStringSecretName": { + "type": "string", "nullable": true, - "minValue": -1, - "maxValue": 2147483647, "metadata": { - "description": "Optional. Default to -1. Default time to live (in seconds). With Time to Live or TTL, Azure Cosmos DB provides the ability to delete items automatically from a container after a certain time period. If the value is set to \"-1\", it is equal to infinity, and items don't expire by default." + "description": "Optional. Default to Primary-Readonly-ConnectionString. The primary readonly connection string secret name to create." } }, - "indexingPolicy": { - "type": "object", + "secondaryWriteKeySecretName": { + "type": "string", "nullable": true, "metadata": { - "description": "Optional. Indexing policy of the container." + "description": "Optional. Default to Secondary-Write-Key. The primary write key secret name to create." } }, - "kind": { + "secondaryReadonlyKeySecretName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Default to Secondary-Readonly-Key. The primary readonly key secret name to create." + } + }, + "secondaryWriteConnectionStringSecretName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Default to Secondary-Write-ConnectionString. The primary write connection string secret name to create." + } + }, + "secondaryReadonlyConnectionStringSecretName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Default to Secondary-Readonly-ConnectionString. The primary readonly connection string secret name to create." + } + } + } + }, + "networkRestrictionsType": { + "type": "object", + "properties": { + "ipRules": { + "type": "array", + "items": { + "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\"." + } + }, + "networkAclBypass": { "type": "string", "allowedValues": [ - "Hash", - "MultiHash", - "Range" + "AzureServices", + "None" ], "nullable": true, "metadata": { - "description": "Optional. Default to Hash. Indicates the kind of algorithm used for partitioning." + "description": "Optional. Default to AzureServices. Specifies the network ACL bypass for Azure services." } }, - "throughput": { - "type": "int", + "publicNetworkAccess": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], "nullable": true, "metadata": { - "description": "Optional. Default to 400. Request Units per second. Will be ignored if autoscaleSettingsMaxThroughput is used." + "description": "Optional. Default to Enabled. Whether requests from Public Network are allowed." } }, - "uniqueKeyPolicyKeys": { + "virtualNetworkRules": { "type": "array", "items": { "type": "object", "properties": { - "paths": { - "type": "array", - "items": { - "type": "string" - }, + "subnetResourceId": { + "type": "string", "metadata": { - "description": "List of paths must be unique for each document in the Azure Cosmos DB service" + "description": "Required. Resource ID of a subnet." } } } }, - "nullable": true, "metadata": { - "description": "Optional. The unique key policy configuration containing a list of unique keys that enforces uniqueness constraint on documents in the collection in the Azure Cosmos DB service." + "description": "Optional. Default to []. List of Virtual Network ACL rules configured for the Cosmos DB account.." } } } @@ -654,10 +778,11 @@ "locations": { "type": "array", "items": { - "$ref": "#/definitions/failoverLocations" + "$ref": "#/definitions/failoverLocationsType" }, + "defaultValue": [], "metadata": { - "description": "Required. Locations enabled for the Cosmos DB account." + "description": "Optional. Default to the location where the account is deployed. Locations enabled for the Cosmos DB account." } }, "defaultConsistencyLevel": { @@ -702,6 +827,20 @@ "description": "Optional. Default to false. Flag to indicate whether Free Tier is enabled." } }, + "enableMultipleWriteLocations": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Default to false. Enables the account to write in multiple locations. Periodic backup must be used if enabled." + } + }, + "disableKeyBasedMetadataWriteAccess": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Default to false. Disable write operations on metadata resources (databases, containers, throughput) via account keys." + } + }, "maxStalenessPrefix": { "type": "int", "defaultValue": 100000, @@ -736,7 +875,7 @@ "sqlDatabases": { "type": "array", "items": { - "$ref": "#/definitions/sqlDatabase" + "$ref": "#/definitions/sqlDatabaseType" }, "defaultValue": [], "metadata": { @@ -808,7 +947,7 @@ "Continuous" ], "metadata": { - "description": "Optional. Default to Continuous. Describes the mode of backups." + "description": "Optional. Default to Continuous. Describes the mode of backups. Periodic backup must be used if multiple write locations are used." } }, "backupPolicyContinuousTier": { @@ -857,6 +996,20 @@ "metadata": { "description": "Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible." } + }, + "secretsKeyVault": { + "$ref": "#/definitions/secretsKeyVaultType", + "nullable": true, + "metadata": { + "description": "Optional. Key vault reference and secret settings to add the connection strings and keys generated by the cosmosdb account." + } + }, + "networkRestrictions": { + "$ref": "#/definitions/networkRestrictionsType", + "nullable": true, + "metadata": { + "description": "Optional. The network configuration of this module." + } } }, "variables": { @@ -866,8 +1019,8 @@ "count": "[length(parameters('locations'))]", "input": { "failoverPriority": "[parameters('locations')[copyIndex('databaseAccount_locations')].failoverPriority]", - "isZoneRedundant": "[parameters('locations')[copyIndex('databaseAccount_locations')].isZoneRedundant]", - "locationName": "[parameters('locations')[copyIndex('databaseAccount_locations')].locationName]" + "locationName": "[parameters('locations')[copyIndex('databaseAccount_locations')].locationName]", + "isZoneRedundant": "[coalesce(tryGet(parameters('locations')[copyIndex('databaseAccount_locations')], 'isZoneRedundant'), true())]" } }, { @@ -876,6 +1029,21 @@ "input": { "name": "[parameters('capabilitiesToAdd')[copyIndex('capabilities')]]" } + }, + { + "name": "ipRules", + "count": "[length(coalesce(tryGet(parameters('networkRestrictions'), 'ipRules'), createArray()))]", + "input": { + "ipAddressOrRange": "[coalesce(tryGet(parameters('networkRestrictions'), 'ipRules'), createArray())[copyIndex('ipRules')]]" + } + }, + { + "name": "virtualNetworkRules", + "count": "[length(coalesce(tryGet(parameters('networkRestrictions'), 'virtualNetworkRules'), createArray()))]", + "input": { + "id": "[coalesce(tryGet(parameters('networkRestrictions'), 'virtualNetworkRules'), createArray())[copyIndex('virtualNetworkRules')].subnetResourceId]", + "ignoreMissingVnetServiceEndpoint": false + } } ], "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'))))]", @@ -899,9 +1067,16 @@ "defaultConsistencyLevel": "Strong" } }, - "kind": "[if(or(not(empty(parameters('sqlDatabases'))), not(empty(parameters('gremlinDatabases')))), 'GlobalDocumentDB', if(not(empty(parameters('mongodbDatabases'))), 'MongoDB', 'Parse'))]", + "defaultFailoverLocation": [ + { + "failoverPriority": 0, + "locationName": "[parameters('location')]", + "isZoneRedundant": true + } + ], + "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'))))]", - "databaseAccount_properties": "[union(createObject('databaseAccountOfferType', parameters('databaseAccountOfferType')), if(or(or(not(empty(parameters('sqlDatabases'))), not(empty(parameters('mongodbDatabases')))), not(empty(parameters('gremlinDatabases')))), createObject('consistencyPolicy', variables('consistencyPolicy')[parameters('defaultConsistencyLevel')], 'locations', variables('databaseAccount_locations'), 'capabilities', variables('capabilities'), 'enableFreeTier', parameters('enableFreeTier'), 'backupPolicy', variables('backupPolicy'), 'enableAutomaticFailover', parameters('automaticFailover'), 'enableAnalyticalStorage', parameters('enableAnalyticalStorage')), createObject()), if(not(empty(parameters('sqlDatabases'))), createObject('disableLocalAuth', parameters('disableLocalAuth')), createObject()), if(not(empty(parameters('mongodbDatabases'))), createObject('apiProperties', createObject('serverVersion', parameters('serverVersion'))), createObject()))]", + "databaseAccount_properties": "[union(createObject('databaseAccountOfferType', parameters('databaseAccountOfferType')), 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'), 'backupPolicy', variables('backupPolicy'), '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()))]", "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')]", @@ -1060,8 +1235,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "1307928694299767068" + "version": "0.26.54.24096", + "templateHash": "3826907101153138616" }, "name": "DocumentDB Database Account SQL Databases", "description": "This module deploys a SQL Database in a CosmosDB Account.", @@ -1190,8 +1365,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "8159752253553558916" + "version": "0.26.54.24096", + "templateHash": "11250469246171251281" }, "name": "DocumentDB Database Account SQL Database Containers", "description": "This module deploys a SQL Database Container in a CosmosDB Account.", @@ -1299,6 +1474,16 @@ } } }, + "variables": { + "copy": [ + { + "name": "partitionKeyPaths", + "count": "[length(parameters('paths'))]", + "input": "[if(startsWith(parameters('paths')[copyIndex('partitionKeyPaths')], '/'), parameters('paths')[copyIndex('partitionKeyPaths')], format('/{0}', parameters('paths')[copyIndex('partitionKeyPaths')]))]" + } + ], + "containerResourceParams": "[union(createObject('conflictResolutionPolicy', parameters('conflictResolutionPolicy'), 'defaultTtl', parameters('defaultTtl'), 'id', parameters('name'), 'indexingPolicy', if(not(empty(parameters('indexingPolicy'))), parameters('indexingPolicy'), null()), 'partitionKey', createObject('paths', variables('partitionKeyPaths'), 'kind', parameters('kind'), 'version', if(equals(parameters('kind'), 'MultiHash'), 2, 1)), 'uniqueKeyPolicy', if(not(empty(parameters('uniqueKeyPolicyKeys'))), createObject('uniqueKeys', parameters('uniqueKeyPolicyKeys')), null())), if(not(equals(parameters('analyticalStorageTtl'), 0)), createObject('analyticalStorageTtl', parameters('analyticalStorageTtl')), createObject()))]" + }, "resources": { "databaseAccount::sqlDatabase": { "existing": true, @@ -1321,25 +1506,7 @@ "name": "[format('{0}/{1}/{2}', parameters('databaseAccountName'), parameters('sqlDatabaseName'), parameters('name'))]", "tags": "[parameters('tags')]", "properties": { - "resource": { - "analyticalStorageTtl": "[parameters('analyticalStorageTtl')]", - "conflictResolutionPolicy": "[parameters('conflictResolutionPolicy')]", - "defaultTtl": "[parameters('defaultTtl')]", - "id": "[parameters('name')]", - "indexingPolicy": "[if(not(empty(parameters('indexingPolicy'))), parameters('indexingPolicy'), null())]", - "partitionKey": { - "copy": [ - { - "name": "paths", - "count": "[length(parameters('paths'))]", - "input": "[if(startsWith(parameters('paths')[copyIndex('paths')], '/'), parameters('paths')[copyIndex('paths')], format('/{0}', parameters('paths')[copyIndex('paths')]))]" - } - ], - "kind": "[parameters('kind')]", - "version": "[if(equals(parameters('kind'), 'MultiHash'), 2, 1)]" - }, - "uniqueKeyPolicy": "[if(not(empty(parameters('uniqueKeyPolicyKeys'))), createObject('uniqueKeys', parameters('uniqueKeyPolicyKeys')), null())]" - }, + "resource": "[variables('containerResourceParams')]", "options": "[if(contains(reference('databaseAccount').capabilities, createObject('name', 'EnableServerless')), null(), createObject('throughput', if(and(equals(parameters('autoscaleSettingsMaxThroughput'), null()), not(equals(parameters('throughput'), -1))), parameters('throughput'), null()), 'autoscaleSettings', if(not(equals(parameters('autoscaleSettingsMaxThroughput'), null())), createObject('maxThroughput', parameters('autoscaleSettingsMaxThroughput')), null())))]" }, "dependsOn": [ @@ -1441,8 +1608,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "5538920636867167805" + "version": "0.26.54.24096", + "templateHash": "7706794569430424680" }, "name": "DocumentDB Database Account MongoDB Databases", "description": "This module deploys a MongoDB Database within a CosmosDB Account.", @@ -1544,8 +1711,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "12727124123085683569" + "version": "0.26.54.24096", + "templateHash": "1989910090472113779" }, "name": "DocumentDB Database Account MongoDB Database Collections", "description": "This module deploys a MongoDB Database Collection.", @@ -1700,8 +1867,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "5227237801347888732" + "version": "0.26.54.24096", + "templateHash": "13414524346849431368" }, "name": "DocumentDB Database Account Gremlin Databases", "description": "This module deploys a Gremlin Database within a CosmosDB Account.", @@ -1804,8 +1971,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4078462189838201163" + "version": "0.26.54.24096", + "templateHash": "2823004405398378621" }, "name": "DocumentDB Database Accounts Gremlin Databases Graphs", "description": "This module deploys a DocumentDB Database Accounts Gremlin Database Graph.", @@ -2606,6 +2773,122 @@ "dependsOn": [ "databaseAccount" ] + }, + "keyVault": { + "condition": "[not(equals(parameters('secretsKeyVault'), null()))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-secrets-kv', uniqueString(deployment().name, parameters('location')))]", + "resourceGroup": "[coalesce(tryGet(parameters('secretsKeyVault'), 'resourceGroupName'), resourceGroup().name)]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "keyVaultName": { + "value": "[parameters('secretsKeyVault').keyVaultName]" + }, + "keySecrets": { + "value": [ + { + "secretName": "[coalesce(tryGet(parameters('secretsKeyVault'), 'primaryWriteKeySecretName'), 'Primary-Write-Key')]", + "secretValue": "[listKeys(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('name')), '2023-04-15').primaryMasterKey]" + }, + { + "secretName": "[coalesce(tryGet(parameters('secretsKeyVault'), 'primaryReadOnlyKeySecretName'), 'Primary-Readonly-Key')]", + "secretValue": "[listKeys(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('name')), '2023-04-15').primaryReadonlyMasterKey]" + }, + { + "secretName": "[coalesce(tryGet(parameters('secretsKeyVault'), 'primaryWriteConnectionStringSecretName'), 'Primary-Write-ConnectionString')]", + "secretValue": "[listConnectionStrings(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('name')), '2023-04-15').connectionStrings[0].connectionString]" + }, + { + "secretName": "[coalesce(tryGet(parameters('secretsKeyVault'), 'primaryReadonlyConnectionStringSecretName'), 'Primary-Readonly-ConnectionString')]", + "secretValue": "[listConnectionStrings(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('name')), '2023-04-15').connectionStrings[2].connectionString]" + }, + { + "secretName": "[coalesce(tryGet(parameters('secretsKeyVault'), 'secondaryWriteKeySecretName'), 'Secondary-Write-Key')]", + "secretValue": "[listKeys(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('name')), '2023-04-15').secondaryMasterKey]" + }, + { + "secretName": "[coalesce(tryGet(parameters('secretsKeyVault'), 'secondaryReadonlyKeySecretName'), 'Secondary-Readonly-Key')]", + "secretValue": "[listKeys(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('name')), '2023-04-15').secondaryReadonlyMasterKey]" + }, + { + "secretName": "[coalesce(tryGet(parameters('secretsKeyVault'), 'secondaryWriteConnectionStringSecretName'), 'Secondary-Write-ConnectionString')]", + "secretValue": "[listConnectionStrings(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('name')), '2023-04-15').connectionStrings[1].connectionString]" + }, + { + "secretName": "[coalesce(tryGet(parameters('secretsKeyVault'), 'secondaryReadonlyConnectionStringSecretName'), 'Secondary-Readonly-ConnectionString')]", + "secretValue": "[listConnectionStrings(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('name')), '2023-04-15').connectionStrings[3].connectionString]" + } + ] + } + }, + "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.26.54.24096", + "templateHash": "3376784638805058420" + } + }, + "definitions": { + "keySecret": { + "type": "object", + "properties": { + "secretName": { + "type": "string" + }, + "secretValue": { + "type": "securestring" + } + } + } + }, + "parameters": { + "keyVaultName": { + "type": "string" + }, + "keySecrets": { + "type": "array", + "items": { + "$ref": "#/definitions/keySecret" + } + } + }, + "resources": { + "kv": { + "existing": true, + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2022-07-01", + "name": "[parameters('keyVaultName')]" + }, + "keySecretsSecrets": { + "copy": { + "name": "keySecretsSecrets", + "count": "[length(parameters('keySecrets'))]" + }, + "type": "Microsoft.KeyVault/vaults/secrets", + "apiVersion": "2022-07-01", + "name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('keySecrets')[copyIndex()].secretName)]", + "properties": { + "value": "[parameters('keySecrets')[copyIndex()].secretValue]" + }, + "dependsOn": [ + "kv" + ] + } + } + } + }, + "dependsOn": [ + "databaseAccount" + ] } }, "outputs": { diff --git a/avm/res/document-db/database-account/modules/secrets-key-vault.bicep b/avm/res/document-db/database-account/modules/secrets-key-vault.bicep new file mode 100644 index 0000000000..6dfb8e6abf --- /dev/null +++ b/avm/res/document-db/database-account/modules/secrets-key-vault.bicep @@ -0,0 +1,21 @@ +param keyVaultName string +param keySecrets keySecret[] + +resource kv 'Microsoft.KeyVault/vaults@2022-07-01' existing = { + name: keyVaultName +} + +resource keySecretsSecrets 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = [for secret in keySecrets: { + name: secret.secretName + parent: kv + properties: { + value: secret.secretValue + } +}] + +type keySecret = { + secretName: string + + @secure() + secretValue: string +} 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 925b996e85..ae74132b53 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.25.53.49325", - "templateHash": "12727124123085683569" + "version": "0.26.54.24096", + "templateHash": "1989910090472113779" }, "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 549aa6394d..781bd56a97 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.25.53.49325", - "templateHash": "5538920636867167805" + "version": "0.26.54.24096", + "templateHash": "7706794569430424680" }, "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.25.53.49325", - "templateHash": "12727124123085683569" + "version": "0.26.54.24096", + "templateHash": "1989910090472113779" }, "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.bicep b/avm/res/document-db/database-account/sql-database/container/main.bicep index 2eba5910fa..31470bcd08 100644 --- a/avm/res/document-db/database-account/sql-database/container/main.bicep +++ b/avm/res/document-db/database-account/sql-database/container/main.bicep @@ -51,6 +51,25 @@ param uniqueKeyPolicyKeys array = [] ]) param kind string = 'Hash' +var partitionKeyPaths = [for path in paths: startsWith(path, '/') ? path : '/${path}'] + +var containerResourceParams = union({ + conflictResolutionPolicy: conflictResolutionPolicy + defaultTtl: defaultTtl + id: name + indexingPolicy: !empty(indexingPolicy) ? indexingPolicy : null + partitionKey: { + paths: partitionKeyPaths + kind: kind + version: kind == 'MultiHash' ? 2 : 1 + } + uniqueKeyPolicy: !empty(uniqueKeyPolicyKeys) ? { + uniqueKeys: uniqueKeyPolicyKeys + } : null + }, analyticalStorageTtl != 0 ? { + analyticalStorageTtl: analyticalStorageTtl // please note that this property is not idempotent + } : {}) + resource databaseAccount 'Microsoft.DocumentDB/databaseAccounts@2023-04-15' existing = { name: databaseAccountName @@ -64,21 +83,7 @@ resource container 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/container parent: databaseAccount::sqlDatabase tags: tags properties: { - resource: { - analyticalStorageTtl: analyticalStorageTtl // please note that this property is not idempotent - conflictResolutionPolicy: conflictResolutionPolicy - defaultTtl: defaultTtl - id: name - indexingPolicy: !empty(indexingPolicy) ? indexingPolicy : null - partitionKey: { - paths: [for path in paths: startsWith(path, '/') ? path : '/${path}'] - kind: kind - version: kind == 'MultiHash' ? 2 : 1 - } - uniqueKeyPolicy: !empty(uniqueKeyPolicyKeys) ? { - uniqueKeys: uniqueKeyPolicyKeys - } : null - } + resource: containerResourceParams options: contains(databaseAccount.properties.capabilities, { name: 'EnableServerless' }) ? null : { throughput: autoscaleSettingsMaxThroughput == null && throughput != -1 ? throughput : null autoscaleSettings: autoscaleSettingsMaxThroughput != null ? { 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 f362c2607e..815512145c 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.25.53.49325", - "templateHash": "8159752253553558916" + "version": "0.26.54.24096", + "templateHash": "11250469246171251281" }, "name": "DocumentDB Database Account SQL Database Containers", "description": "This module deploys a SQL Database Container in a CosmosDB Account.", @@ -114,6 +114,16 @@ } } }, + "variables": { + "copy": [ + { + "name": "partitionKeyPaths", + "count": "[length(parameters('paths'))]", + "input": "[if(startsWith(parameters('paths')[copyIndex('partitionKeyPaths')], '/'), parameters('paths')[copyIndex('partitionKeyPaths')], format('/{0}', parameters('paths')[copyIndex('partitionKeyPaths')]))]" + } + ], + "containerResourceParams": "[union(createObject('conflictResolutionPolicy', parameters('conflictResolutionPolicy'), 'defaultTtl', parameters('defaultTtl'), 'id', parameters('name'), 'indexingPolicy', if(not(empty(parameters('indexingPolicy'))), parameters('indexingPolicy'), null()), 'partitionKey', createObject('paths', variables('partitionKeyPaths'), 'kind', parameters('kind'), 'version', if(equals(parameters('kind'), 'MultiHash'), 2, 1)), 'uniqueKeyPolicy', if(not(empty(parameters('uniqueKeyPolicyKeys'))), createObject('uniqueKeys', parameters('uniqueKeyPolicyKeys')), null())), if(not(equals(parameters('analyticalStorageTtl'), 0)), createObject('analyticalStorageTtl', parameters('analyticalStorageTtl')), createObject()))]" + }, "resources": { "databaseAccount::sqlDatabase": { "existing": true, @@ -136,25 +146,7 @@ "name": "[format('{0}/{1}/{2}', parameters('databaseAccountName'), parameters('sqlDatabaseName'), parameters('name'))]", "tags": "[parameters('tags')]", "properties": { - "resource": { - "analyticalStorageTtl": "[parameters('analyticalStorageTtl')]", - "conflictResolutionPolicy": "[parameters('conflictResolutionPolicy')]", - "defaultTtl": "[parameters('defaultTtl')]", - "id": "[parameters('name')]", - "indexingPolicy": "[if(not(empty(parameters('indexingPolicy'))), parameters('indexingPolicy'), null())]", - "partitionKey": { - "copy": [ - { - "name": "paths", - "count": "[length(parameters('paths'))]", - "input": "[if(startsWith(parameters('paths')[copyIndex('paths')], '/'), parameters('paths')[copyIndex('paths')], format('/{0}', parameters('paths')[copyIndex('paths')]))]" - } - ], - "kind": "[parameters('kind')]", - "version": "[if(equals(parameters('kind'), 'MultiHash'), 2, 1)]" - }, - "uniqueKeyPolicy": "[if(not(empty(parameters('uniqueKeyPolicyKeys'))), createObject('uniqueKeys', parameters('uniqueKeyPolicyKeys')), null())]" - }, + "resource": "[variables('containerResourceParams')]", "options": "[if(contains(reference('databaseAccount').capabilities, createObject('name', 'EnableServerless')), null(), createObject('throughput', if(and(equals(parameters('autoscaleSettingsMaxThroughput'), null()), not(equals(parameters('throughput'), -1))), parameters('throughput'), null()), 'autoscaleSettings', if(not(equals(parameters('autoscaleSettingsMaxThroughput'), null())), createObject('maxThroughput', parameters('autoscaleSettingsMaxThroughput')), null())))]" }, "dependsOn": [ 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 ca95db8b40..0419417fa5 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.25.53.49325", - "templateHash": "1307928694299767068" + "version": "0.26.54.24096", + "templateHash": "3826907101153138616" }, "name": "DocumentDB Database Account SQL Databases", "description": "This module deploys a SQL Database in a CosmosDB Account.", @@ -135,8 +135,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "8159752253553558916" + "version": "0.26.54.24096", + "templateHash": "11250469246171251281" }, "name": "DocumentDB Database Account SQL Database Containers", "description": "This module deploys a SQL Database Container in a CosmosDB Account.", @@ -244,6 +244,16 @@ } } }, + "variables": { + "copy": [ + { + "name": "partitionKeyPaths", + "count": "[length(parameters('paths'))]", + "input": "[if(startsWith(parameters('paths')[copyIndex('partitionKeyPaths')], '/'), parameters('paths')[copyIndex('partitionKeyPaths')], format('/{0}', parameters('paths')[copyIndex('partitionKeyPaths')]))]" + } + ], + "containerResourceParams": "[union(createObject('conflictResolutionPolicy', parameters('conflictResolutionPolicy'), 'defaultTtl', parameters('defaultTtl'), 'id', parameters('name'), 'indexingPolicy', if(not(empty(parameters('indexingPolicy'))), parameters('indexingPolicy'), null()), 'partitionKey', createObject('paths', variables('partitionKeyPaths'), 'kind', parameters('kind'), 'version', if(equals(parameters('kind'), 'MultiHash'), 2, 1)), 'uniqueKeyPolicy', if(not(empty(parameters('uniqueKeyPolicyKeys'))), createObject('uniqueKeys', parameters('uniqueKeyPolicyKeys')), null())), if(not(equals(parameters('analyticalStorageTtl'), 0)), createObject('analyticalStorageTtl', parameters('analyticalStorageTtl')), createObject()))]" + }, "resources": { "databaseAccount::sqlDatabase": { "existing": true, @@ -266,25 +276,7 @@ "name": "[format('{0}/{1}/{2}', parameters('databaseAccountName'), parameters('sqlDatabaseName'), parameters('name'))]", "tags": "[parameters('tags')]", "properties": { - "resource": { - "analyticalStorageTtl": "[parameters('analyticalStorageTtl')]", - "conflictResolutionPolicy": "[parameters('conflictResolutionPolicy')]", - "defaultTtl": "[parameters('defaultTtl')]", - "id": "[parameters('name')]", - "indexingPolicy": "[if(not(empty(parameters('indexingPolicy'))), parameters('indexingPolicy'), null())]", - "partitionKey": { - "copy": [ - { - "name": "paths", - "count": "[length(parameters('paths'))]", - "input": "[if(startsWith(parameters('paths')[copyIndex('paths')], '/'), parameters('paths')[copyIndex('paths')], format('/{0}', parameters('paths')[copyIndex('paths')]))]" - } - ], - "kind": "[parameters('kind')]", - "version": "[if(equals(parameters('kind'), 'MultiHash'), 2, 1)]" - }, - "uniqueKeyPolicy": "[if(not(empty(parameters('uniqueKeyPolicyKeys'))), createObject('uniqueKeys', parameters('uniqueKeyPolicyKeys')), null())]" - }, + "resource": "[variables('containerResourceParams')]", "options": "[if(contains(reference('databaseAccount').capabilities, createObject('name', 'EnableServerless')), null(), createObject('throughput', if(and(equals(parameters('autoscaleSettingsMaxThroughput'), null()), not(equals(parameters('throughput'), -1))), parameters('throughput'), null()), 'autoscaleSettings', if(not(equals(parameters('autoscaleSettingsMaxThroughput'), null())), createObject('maxThroughput', parameters('autoscaleSettingsMaxThroughput')), null())))]" }, "dependsOn": [ 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 7be10fac8a..2ea410a71c 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 @@ -21,7 +21,7 @@ param serviceShort string = 'dddaanl' param namePrefix string = '#_namePrefix_#' // Pipeline is selecting random regions which dont support all cosmos features and have constraints when creating new cosmos -var enforcedLocation = 'eastus' +var enforcedLocation = 'eastasia' // ============== // // General resources @@ -42,16 +42,9 @@ module testDeployment '../../../main.bicep' = { location: enforcedLocation enableAnalyticalStorage: true name: '${namePrefix}-analytical' - locations: [ - { - failoverPriority: 0 - isZoneRedundant: false - locationName: enforcedLocation - } - ] sqlDatabases: [ { - name: 'empty-database' + name: 'no-containers-specified' } ] } diff --git a/avm/res/document-db/database-account/tests/e2e/consistency/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/boundedConsistency/main.test.bicep similarity index 89% rename from avm/res/document-db/database-account/tests/e2e/consistency/main.test.bicep rename to avm/res/document-db/database-account/tests/e2e/boundedConsistency/main.test.bicep index 8dbaa8440e..3d27d57753 100644 --- a/avm/res/document-db/database-account/tests/e2e/consistency/main.test.bicep +++ b/avm/res/document-db/database-account/tests/e2e/boundedConsistency/main.test.bicep @@ -21,7 +21,7 @@ param serviceShort string = 'dddabco' param namePrefix string = '#_namePrefix_#' // Pipeline is selecting random regions which dont support all cosmos features and have constraints when creating new cosmos -var enforcedLocation = 'eastus' +var enforcedLocation = 'eastasia' // ============== // // General resources @@ -44,16 +44,9 @@ module testDeployment '../../../main.bicep' = { defaultConsistencyLevel: 'BoundedStaleness' maxIntervalInSeconds: 600 maxStalenessPrefix: 200000 - locations: [ - { - failoverPriority: 0 - isZoneRedundant: false - locationName: enforcedLocation - } - ] sqlDatabases: [ { - name: 'empty-database' + name: 'no-containers-specified' } ] } diff --git a/avm/res/document-db/database-account/tests/e2e/continousBckup/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/continousBckup/main.test.bicep deleted file mode 100644 index 0f4d2dda33..0000000000 --- a/avm/res/document-db/database-account/tests/e2e/continousBckup/main.test.bicep +++ /dev/null @@ -1,59 +0,0 @@ -targetScope = 'subscription' - -metadata name = 'Enabling continous backups' -metadata description = 'This instance deploys the module enabling continous backups.' - -// ========== // -// 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. 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 = 'dddacbc' - -@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 -var enforcedLocation = 'eastus' - -// ============== // -// General resources -// ============== // -resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { - name: resourceGroupName - location: enforcedLocation -} - -// ============== // -// Test Execution // -// ============== // - -module testDeployment '../../../main.bicep' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}' - params: { - location: enforcedLocation - name: '${namePrefix}-continous-bckup' - backupPolicyType: 'Continuous' - backupPolicyContinuousTier: 'Continuous7Days' - locations: [ - { - failoverPriority: 0 - isZoneRedundant: false - locationName: enforcedLocation - } - ] - sqlDatabases: [ - { - name: 'empty-database' - } - ] - } -} 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 d925e18d86..85a5bde529 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 @@ -21,7 +21,7 @@ param serviceShort string = 'dddamin' param namePrefix string = '#_namePrefix_#' // Pipeline is selecting random regions which dont support all cosmos features and have constraints when creating new cosmos -var enforcedLocation = 'eastus' +var enforcedLocation = 'eastasia' // ============ // // Dependencies // @@ -43,14 +43,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}-${iteration}' params: { - name: '${namePrefix}${serviceShort}001' location: enforcedLocation - locations: [ - { - failoverPriority: 0 - isZoneRedundant: false - locationName: enforcedLocation - } - ] + name: '${namePrefix}${serviceShort}001' } }] diff --git a/avm/res/document-db/database-account/tests/e2e/disableLocal/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/disableLocal/main.test.bicep deleted file mode 100644 index 78320d234b..0000000000 --- a/avm/res/document-db/database-account/tests/e2e/disableLocal/main.test.bicep +++ /dev/null @@ -1,57 +0,0 @@ -targetScope = 'subscription' - -metadata name = 'Disabling local authentication. i.e. access keys' -metadata description = 'This instance deploys the module disabling local authentication.' - -// ========== // -// 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. 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 = 'dddadlo' - -@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 -var enforcedLocation = 'eastus' - -// General resources -// ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { - name: resourceGroupName - location: enforcedLocation -} - -// ============== // -// Test Execution // -// ============== // - -module testDeployment '../../../main.bicep' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}' - params: { - disableLocalAuth: true - location: enforcedLocation - name: '${namePrefix}-local-auth-off' - locations: [ - { - failoverPriority: 0 - isZoneRedundant: false - locationName: enforcedLocation - } - ] - sqlDatabases: [ - { - name: 'empty-database' - } - ] - } -} 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 9e03bcf942..5501a878a7 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 @@ -21,7 +21,7 @@ param serviceShort string = 'dddagrm' param namePrefix string = '#_namePrefix_#' // Pipeline is selecting random regions which dont support all cosmos features and have constraints when creating new cosmos -var enforcedLocation = 'eastus' +var enforcedLocation = 'eastasia' // ============ // // Dependencies // diff --git a/avm/res/document-db/database-account/tests/e2e/kvSecrets/dependencies.bicep b/avm/res/document-db/database-account/tests/e2e/kvSecrets/dependencies.bicep new file mode 100644 index 0000000000..caa4813d58 --- /dev/null +++ b/avm/res/document-db/database-account/tests/e2e/kvSecrets/dependencies.bicep @@ -0,0 +1,21 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Managed Identity to create.') +param keyVaultName string + +resource keyVault 'Microsoft.KeyVault/vaults@2021-06-01-preview' = { + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' + } + enableRbacAuthorization: true + tenantId: subscription().tenantId + } +} + +@description('The name of the Key Vault created.') +output keyVaultName string = keyVaultName diff --git a/avm/res/document-db/database-account/tests/e2e/systemMi/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/kvSecrets/main.test.bicep similarity index 64% rename from avm/res/document-db/database-account/tests/e2e/systemMi/main.test.bicep rename to avm/res/document-db/database-account/tests/e2e/kvSecrets/main.test.bicep index bc2c279055..1fcfbe4d43 100644 --- a/avm/res/document-db/database-account/tests/e2e/systemMi/main.test.bicep +++ b/avm/res/document-db/database-account/tests/e2e/kvSecrets/main.test.bicep @@ -1,7 +1,7 @@ targetScope = 'subscription' -metadata name = 'Deploying with a System-Assigned Identity' -metadata description = 'This instance deploys the module with an assigned system assigned managed identity.' +metadata name = 'Deploying with a key vault reference to save secrets' +metadata description = 'This instance deploys the module saving all its secrets in a key vault.' // ========== // // Parameters // @@ -15,13 +15,13 @@ param resourceGroupName string = 'dep-${namePrefix}-documentdb.databaseaccounts- 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 = 'dddasmi' +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 -var enforcedLocation = 'eastus' +var enforcedLocation = 'eastasia' // ============== // // General resources @@ -31,6 +31,15 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { location: enforcedLocation } +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-nestedDependencies' + params: { + keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}' + location: enforcedLocation + } +} + // ============== // // Test Execution // // ============== // @@ -40,16 +49,10 @@ module testDeployment '../../../main.bicep' = { name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}' params: { location: enforcedLocation - name: '${namePrefix}-system-mi' - locations: [ - { - failoverPriority: 0 - isZoneRedundant: false - locationName: enforcedLocation - } - ] - managedIdentities: { - systemAssigned: true + name: '${namePrefix}-kv-ref' + secretsKeyVault: { + keyVaultName: nestedDependencies.outputs.keyVaultName + primaryReadonlyConnectionStringSecretName: 'custom-secret-name' } } } diff --git a/avm/res/document-db/database-account/tests/e2e/plain/dependencies.bicep b/avm/res/document-db/database-account/tests/e2e/managedIdentity/dependencies.bicep similarity index 91% rename from avm/res/document-db/database-account/tests/e2e/plain/dependencies.bicep rename to avm/res/document-db/database-account/tests/e2e/managedIdentity/dependencies.bicep index 067f558eb5..078aeb1cf1 100644 --- a/avm/res/document-db/database-account/tests/e2e/plain/dependencies.bicep +++ b/avm/res/document-db/database-account/tests/e2e/managedIdentity/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The resource ID of the created Managed Identity.') diff --git a/avm/res/document-db/database-account/tests/e2e/userMi/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/managedIdentity/main.test.bicep similarity index 70% rename from avm/res/document-db/database-account/tests/e2e/userMi/main.test.bicep rename to avm/res/document-db/database-account/tests/e2e/managedIdentity/main.test.bicep index 4db70eaae4..e3f1aec577 100644 --- a/avm/res/document-db/database-account/tests/e2e/userMi/main.test.bicep +++ b/avm/res/document-db/database-account/tests/e2e/managedIdentity/main.test.bicep @@ -1,7 +1,7 @@ targetScope = 'subscription' -metadata name = 'Deploying with a User-Assigned Identity' -metadata description = 'This instance deploys the module with an assigned user assigned managed identity.' +metadata name = 'Deploying with Managed identities' +metadata description = 'This instance deploys the module with an system and user assigned managed identity.' // ========== // // Parameters // @@ -21,7 +21,7 @@ param serviceShort string = 'dddaumi' param namePrefix string = '#_namePrefix_#' // Pipeline is selecting random regions which dont support all cosmos features and have constraints when creating new cosmos -var enforcedLocation = 'eastus' +var enforcedLocation = 'eastasia' // ============ // // Dependencies // @@ -54,18 +54,29 @@ module testDeployment '../../../main.bicep' = { params: { location: enforcedLocation name: '${namePrefix}-user-mi' - locations: [ - { - failoverPriority: 0 - isZoneRedundant: false - locationName: enforcedLocation - } - ] managedIdentities: { + systemAssigned: true userAssignedResourceIds: [ nestedDependencies.outputs.managedIdentityResourceId ] } + 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' + } + ] } dependsOn: [ nestedDependencies 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 e3fd85af54..fac03ce28c 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 @@ -21,7 +21,7 @@ param serviceShort string = 'dddamng' param namePrefix string = '#_namePrefix_#' // Pipeline is selecting random regions which dont support all cosmos features and have constraints when creating new cosmos -var enforcedLocation = 'eastus' +var enforcedLocation = 'eastasia' // ============ // // Dependencies // diff --git a/avm/res/document-db/database-account/tests/e2e/autoFailoverOff/dependencies.bicep b/avm/res/document-db/database-account/tests/e2e/multiRegion/dependencies.bicep similarity index 100% rename from avm/res/document-db/database-account/tests/e2e/autoFailoverOff/dependencies.bicep rename to avm/res/document-db/database-account/tests/e2e/multiRegion/dependencies.bicep diff --git a/avm/res/document-db/database-account/tests/e2e/autoFailoverOff/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/multiRegion/main.test.bicep similarity index 77% rename from avm/res/document-db/database-account/tests/e2e/autoFailoverOff/main.test.bicep rename to avm/res/document-db/database-account/tests/e2e/multiRegion/main.test.bicep index 7e83765872..988eaf2864 100644 --- a/avm/res/document-db/database-account/tests/e2e/autoFailoverOff/main.test.bicep +++ b/avm/res/document-db/database-account/tests/e2e/multiRegion/main.test.bicep @@ -1,7 +1,7 @@ targetScope = 'subscription' -metadata name = 'Without automatic failover' -metadata description = 'This instance deploys the module disabling automatic failover.' +metadata name = 'Deploying multiple regions' +metadata description = 'This instance deploys the module in multiple regions with configs specific of multi region scenarios.' // ========== // // Parameters // @@ -15,13 +15,13 @@ param resourceGroupName string = 'dep-${namePrefix}-documentdb.databaseaccounts- 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 = 'dddaauo' +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 -var enforcedLocation = 'eastus' +var enforcedLocation = 'eastasia' // ============ // // Dependencies // @@ -55,22 +55,27 @@ module testDeployment '../../../main.bicep' = { params: { automaticFailover: false location: enforcedLocation - name: '${namePrefix}-auto-failover-off' + backupPolicyType: 'Periodic' + backupIntervalInMinutes: 300 + backupStorageRedundancy: 'Zone' + backupRetentionIntervalInHours: 16 + enableMultipleWriteLocations: true + name: '${namePrefix}-multi-region' locations: [ { failoverPriority: 0 - isZoneRedundant: false + isZoneRedundant: true locationName: enforcedLocation } { failoverPriority: 1 - isZoneRedundant: false + isZoneRedundant: true locationName: nestedDependencies.outputs.pairedRegionName } ] sqlDatabases: [ { - name: 'empty-database' + name: 'no-containers-specified' } ] } diff --git a/avm/res/document-db/database-account/tests/e2e/periodicBckup/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/periodicBckup/main.test.bicep deleted file mode 100644 index d7eb9f3683..0000000000 --- a/avm/res/document-db/database-account/tests/e2e/periodicBckup/main.test.bicep +++ /dev/null @@ -1,61 +0,0 @@ -targetScope = 'subscription' - -metadata name = 'Using periodic backups' -metadata description = 'This instance deploys the module enabling periodic backups.' - -// ========== // -// 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. 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 = 'dddapbc' - -@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 -var enforcedLocation = 'eastus' - -// ============== // -// General resources -// ============== // -resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { - name: resourceGroupName - location: enforcedLocation -} - -// ============== // -// Test Execution // -// ============== // - -module testDeployment '../../../main.bicep' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}' - params: { - location: enforcedLocation - name: '${namePrefix}-periodic-bckup' - backupPolicyType: 'Periodic' - backupIntervalInMinutes: 300 - backupStorageRedundancy: 'Zone' - backupRetentionIntervalInHours: 16 - locations: [ - { - failoverPriority: 0 - isZoneRedundant: false - locationName: enforcedLocation - } - ] - sqlDatabases: [ - { - name: 'empty-database' - } - ] - } -} 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 0c9adcc64d..580ad44386 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 @@ -21,20 +21,7 @@ param serviceShort string = 'dddapln' param namePrefix string = '#_namePrefix_#' // Pipeline is selecting random regions which dont support all cosmos features and have constraints when creating new cosmos -var enforcedLocation = 'eastus' - -// ============ // -// Dependencies // -// ============ // - -module nestedDependencies 'dependencies.bicep' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, enforcedLocation)}-nestedDependencies' - params: { - managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' - location: enforcedLocation - } -} +var enforcedLocation = 'eastasia' // ============== // // General resources @@ -44,21 +31,6 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { location: enforcedLocation } -// ============== // -// Diagnostics -// ============== // -module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { - scope: resourceGroup - 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: enforcedLocation - } -} - // ============== // // Test Execution // // ============== // @@ -70,6 +42,11 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' params: { name: '${namePrefix}${serviceShort}001' location: enforcedLocation + disableLocalAuth: true + backupPolicyType: 'Continuous' + disableKeyBasedMetadataWriteAccess: true + defaultConsistencyLevel: 'ConsistentPrefix' + backupPolicyContinuousTier: 'Continuous7Days' locations: [ { failoverPriority: 0 @@ -77,49 +54,10 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' locationName: enforcedLocation } ] - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } + sqlDatabases: [ { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + name: 'no-containers-specified' } ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] }] diff --git a/avm/res/document-db/database-account/tests/e2e/publicRestrictedAccess/dependencies.bicep b/avm/res/document-db/database-account/tests/e2e/publicRestrictedAccess/dependencies.bicep new file mode 100644 index 0000000000..1ea8580f0f --- /dev/null +++ b/avm/res/document-db/database-account/tests/e2e/publicRestrictedAccess/dependencies.bicep @@ -0,0 +1,35 @@ +@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@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + serviceEndpoints: [ + { + service: 'Microsoft.AzureCosmosDB' + } + ] + } + } + ] + } +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id 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 new file mode 100644 index 0000000000..2cc20220ba --- /dev/null +++ b/avm/res/document-db/database-account/tests/e2e/publicRestrictedAccess/main.test.bicep @@ -0,0 +1,78 @@ +targetScope = 'subscription' + +metadata name = 'Public network restricted access with ACL' +metadata description = 'This instance deploys the module with public network access enabled but restricted to IPs, CIDRS or subnets.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +// e.g., for a module 'network/private-endpoint' you could use 'dep-dev-network.privateendpoints-${serviceShort}-rg' +param resourceGroupName string = 'dep-${namePrefix}-documentdb.databaseaccounts-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param resourceLocation string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +// e.g., for a module 'network/private-endpoint' you could use 'npe' as a prefix and then 'waf' as a suffix for the waf-aligned test +param serviceShort string = '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 +var enforcedLocation = 'eastasia' + +// ============ // +// Dependencies // +// ============ // + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-nestedDependencies' + params: { + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + location: enforcedLocation + } +} + +// ============== // +// General resources +// ============== // +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: enforcedLocation +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../../main.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}' + params: { + name: '${namePrefix}${serviceShort}001' + location: enforcedLocation + networkRestrictions: { + publicNetworkAccess: 'Enabled' + networkAclBypass: 'AzureServices' + ipRules: [ '79.0.0.0', '80.0.0.0' ] + virtualNetworkRules: [ + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + } + ] + } + sqlDatabases: [ + { + name: 'no-containers-specified' + } + ] + } + dependsOn: [ + nestedDependencies + ] +} 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 113f8a0e2e..4185e69934 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 @@ -21,7 +21,7 @@ param serviceShort string = 'dddasql' param namePrefix string = '#_namePrefix_#' // Pipeline is selecting random regions which dont support all cosmos features and have constraints when creating new cosmos -var enforcedLocation = 'eastus' +var enforcedLocation = 'eastasia' // ============== // // General resources diff --git a/avm/res/document-db/database-account/tests/e2e/userMi/dependencies.bicep b/avm/res/document-db/database-account/tests/e2e/userMi/dependencies.bicep deleted file mode 100644 index 067f558eb5..0000000000 --- a/avm/res/document-db/database-account/tests/e2e/userMi/dependencies.bicep +++ /dev/null @@ -1,16 +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 - -resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: managedIdentityName - location: location -} - -@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/document-db/database-account/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/document-db/database-account/tests/e2e/waf-aligned/dependencies.bicep index e42185366b..9289c219a2 100644 --- a/avm/res/document-db/database-account/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/document-db/database-account/tests/e2e/waf-aligned/dependencies.bicep @@ -1,15 +1,9 @@ @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 Virtual Network to create.') param virtualNetworkName string -@description('Required. The name of the Deployment Script to create to get the paired region name.') -param pairedRegionScriptName string - var addressPrefix = '10.0.0.0/16' resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { @@ -48,44 +42,6 @@ resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { } } -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 - @description('The resource ID of the created Virtual Network Subnet.') output subnetResourceId string = virtualNetwork.properties.subnets[0].id 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 add79ea3be..6cd7818490 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 @@ -23,7 +23,7 @@ param serviceShort string = 'dddawaf' param namePrefix string = '#_namePrefix_#' // Pipeline is selecting random regions which dont support all cosmos features and have constraints when creating new cosmos -var enforcedLocation = 'eastus' +var enforcedLocation = 'eastasia' // ============ // // Dependencies // @@ -33,9 +33,7 @@ module nestedDependencies 'dependencies.bicep' = { scope: resourceGroup name: '${uniqueString(deployment().name, enforcedLocation)}-nestedDependencies' params: { - managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' - pairedRegionScriptName: 'dep-${namePrefix}-ds-${serviceShort}' location: enforcedLocation } } @@ -72,18 +70,12 @@ module testDeployment '../../../main.bicep' = { name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}' params: { name: '${namePrefix}${serviceShort}001' - locations: [ - { - failoverPriority: 0 - isZoneRedundant: false - locationName: enforcedLocation - } - { - failoverPriority: 1 - isZoneRedundant: false - locationName: nestedDependencies.outputs.pairedRegionName - } - ] + location: enforcedLocation + disableKeyBasedMetadataWriteAccess: true + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } diagnosticSettings: [ { eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName @@ -92,7 +84,6 @@ module testDeployment '../../../main.bicep' = { workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } ] - location: enforcedLocation privateEndpoints: [ { privateDnsZoneResourceIds: [ @@ -111,37 +102,14 @@ module testDeployment '../../../main.bicep' = { { containers: [ { - kind: 'Hash' name: 'container-001' - indexingPolicy: { - automatic: true - } + kind: 'Hash' paths: [ - '/myPartitionKey' - ] - analyticalStorageTtl: 0 - conflictResolutionPolicy: { - conflictResolutionPath: '/myCustomId' - mode: 'LastWriterWins' - } - defaultTtl: 1000 - uniqueKeyPolicyKeys: [ - { - paths: [ - '/firstName' - ] - } - { - paths: [ - '/lastName' - ] - } + '/myPartitionKey1' ] - throughput: 600 } ] name: '${namePrefix}-sql-${serviceShort}-001' - throughput: 1000 } ] tags: { diff --git a/avm/res/document-db/database-account/tests/e2e/zoneRedundant/main.test.bicep b/avm/res/document-db/database-account/tests/e2e/zoneRedundant/main.test.bicep deleted file mode 100644 index a8db0dad34..0000000000 --- a/avm/res/document-db/database-account/tests/e2e/zoneRedundant/main.test.bicep +++ /dev/null @@ -1,52 +0,0 @@ -targetScope = 'subscription' - -metadata name = 'Using zone redundant regions' -metadata description = 'This instance deploys the module enabling multiple zone redundant in multiple regions.' - -// ========== // -// 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. 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 = 'dddazr' - -@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 -var enforcedLocation = 'eastus' - -// ============== // -// General resources -// ============== // -resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { - name: resourceGroupName - location: enforcedLocation -} - -// ============== // -// Test Execution // -// ============== // - -module testDeployment '../../../main.bicep' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}' - params: { - location: enforcedLocation - name: '${namePrefix}-zone-redundant' - locations: [ - { - failoverPriority: 0 - isZoneRedundant: true - locationName: enforcedLocation - } - ] - } -} diff --git a/avm/res/document-db/database-account/version.json b/avm/res/document-db/database-account/version.json index c177b1bb58..3f863a2bec 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.3", + "version": "0.4", "pathFilters": [ "./main.json" ] From 09080ae987869193f439888b5e1b52871f085ce6 Mon Sep 17 00:00:00 2001 From: Kris Baranek Date: Tue, 26 Mar 2024 12:30:57 +0100 Subject: [PATCH 65/73] fix: Fixing static validation in multiple modules (#1422) ## Description Fixes static tests in following modules: - `avm/res/machine-learning-services/workspace` - Fixes #1354 - `avm/res/recovery-services/vault` - Fixes #1351 - `avm/res/signal-r-service/signal-r` - Fixes #1352 - `avm/res/signal-r-service/web-pub-sub` - Fixes #1356 - `avm/res/machine-learning-services/workspace` - Fixes #1357 ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.machine-learning-services.workspace](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.machine-learning-services.workspace.yml/badge.svg?branch=users%2Fkrbar%2FwebPubSubFix)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.machine-learning-services.workspace.yml) | | [![avm.res.recovery-services.vault](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.recovery-services.vault.yml/badge.svg?branch=users%2Fkrbar%2FwebPubSubFix)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.recovery-services.vault.yml) | | [![avm.res.signal-r-service.signal-r](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.signal-r-service.signal-r.yml/badge.svg?branch=users%2Fkrbar%2FwebPubSubFix)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.signal-r-service.signal-r.yml) | | [![avm.res.signal-r-service.web-pub-sub](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.signal-r-service.web-pub-sub.yml/badge.svg?branch=users%2Fkrbar%2FwebPubSubFix)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.signal-r-service.web-pub-sub.yml) | | [![avm.res.synapse.workspace](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.synapse.workspace.yml/badge.svg?branch=users%2Fkrbar%2FwebPubSubFix)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.synapse.workspace.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [x] Azure Verified Module updates: - [x] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [x] I have run `Set-AVMModule` locally to generate the supporting module files. - [x] My corresponding pipelines / checks run clean and green without any errors or warnings --- avm/res/machine-learning-services/workspace/README.md | 2 +- avm/res/recovery-services/vault/README.md | 10 +++++----- avm/res/signal-r-service/signal-r/README.md | 2 +- avm/res/signal-r-service/web-pub-sub/README.md | 2 +- avm/res/synapse/workspace/README.md | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/avm/res/machine-learning-services/workspace/README.md b/avm/res/machine-learning-services/workspace/README.md index dec8862463..d123fc8d10 100644 --- a/avm/res/machine-learning-services/workspace/README.md +++ b/avm/res/machine-learning-services/workspace/README.md @@ -1,7 +1,7 @@ # Machine Learning Services Workspaces `[Microsoft.MachineLearningServices/workspaces]` > ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ -> +> > - Only security and bug fixes are being handled by the AVM core team at present. > - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! diff --git a/avm/res/recovery-services/vault/README.md b/avm/res/recovery-services/vault/README.md index fcba17825f..cbb123567b 100644 --- a/avm/res/recovery-services/vault/README.md +++ b/avm/res/recovery-services/vault/README.md @@ -56,7 +56,7 @@ This instance deploys the module with the minimum set of required parameters. ```bicep module vault 'br/public:avm/res/recovery-services/vault:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-rsvmin' + name: 'vaultDeployment' params: { // Required parameters name: 'rsvmin001' @@ -136,7 +136,7 @@ This instance deploys the module with disaster recovery enabled. ```bicep module vault 'br/public:avm/res/recovery-services/vault:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-rsvdr' + name: 'vaultDeployment' params: { // Required parameters name: '' @@ -314,7 +314,7 @@ This instance deploys the module with most of its features enabled. ```bicep module vault 'br/public:avm/res/recovery-services/vault:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-rsvmax' + name: 'vaultDeployment' params: { // Required parameters name: 'rsvmax001' @@ -1108,7 +1108,7 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module vault 'br/public:avm/res/recovery-services/vault:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-rsvwaf' + name: 'vaultDeployment' params: { // Required parameters name: 'rsvwaf001' @@ -2643,7 +2643,7 @@ Tags of the Recovery Service Vault resource. ## Cross-referenced modules -This section gives you an overview of all local-referenced module files (i.e., other CARML 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). +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 | | :-- | :-- | diff --git a/avm/res/signal-r-service/signal-r/README.md b/avm/res/signal-r-service/signal-r/README.md index e01d1d7045..7d5d5fdf56 100644 --- a/avm/res/signal-r-service/signal-r/README.md +++ b/avm/res/signal-r-service/signal-r/README.md @@ -1,7 +1,7 @@ # SignalR Service SignalR `[Microsoft.SignalRService/signalR]` > ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ -> +> > - Only security and bug fixes are being handled by the AVM core team at present. > - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! 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 e50d13a31b..bb81947858 100644 --- a/avm/res/signal-r-service/web-pub-sub/README.md +++ b/avm/res/signal-r-service/web-pub-sub/README.md @@ -1,7 +1,7 @@ # SignalR Web PubSub Services `[Microsoft.SignalRService/webPubSub]` > ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ -> +> > - Only security and bug fixes are being handled by the AVM core team at present. > - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! diff --git a/avm/res/synapse/workspace/README.md b/avm/res/synapse/workspace/README.md index 91a6b56496..43e1c84dca 100644 --- a/avm/res/synapse/workspace/README.md +++ b/avm/res/synapse/workspace/README.md @@ -1,7 +1,7 @@ # Synapse Workspaces `[Microsoft.Synapse/workspaces]` > ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ -> +> > - Only security and bug fixes are being handled by the AVM core team at present. > - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! From 8cff4a4e1d3ec20091e3df23ce3b93addb73fd93 Mon Sep 17 00:00:00 2001 From: Kris Baranek Date: Tue, 26 Mar 2024 12:41:49 +0100 Subject: [PATCH 66/73] fix: Fixing `avm/res/synapse/private-link-hub` static tests (#1415) ## Description Fixes static validation of the Synapse Private Link Hub module Fixes #1363 ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.synapse.private-link-hub](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.synapse.private-link-hub.yml/badge.svg?branch=users%2Fkrbar%2FsynapsePLHFix)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.synapse.private-link-hub.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [x] Azure Verified Module updates: - [x] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [x] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [x] I have run `Set-AVMModule` locally to generate the supporting module files. - [x] My corresponding pipelines / checks run clean and green without any errors or warnings --- avm/res/synapse/private-link-hub/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avm/res/synapse/private-link-hub/README.md b/avm/res/synapse/private-link-hub/README.md index d5d10a28d7..5f98f66d01 100644 --- a/avm/res/synapse/private-link-hub/README.md +++ b/avm/res/synapse/private-link-hub/README.md @@ -1,7 +1,7 @@ # Azure Synapse Analytics `[Microsoft.Synapse/privateLinkHubs]` > ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ -> +> > - Only security and bug fixes are being handled by the AVM core team at present. > - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! From 6dda109597687faf6b99567a1d971b3c93f850b8 Mon Sep 17 00:00:00 2001 From: Kris Baranek Date: Tue, 26 Mar 2024 19:04:23 +0100 Subject: [PATCH 67/73] fix: Fixing `avm/res/purview/account` static tests (#1412) ## Description Fixes static validation of the Purview Account module Fixes #1361 ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.purview.account](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.purview.account.yml/badge.svg?branch=users%2Fkrbar%2FpurviewFix)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.purview.account.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [x] Azure Verified Module updates: - [x] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [x] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [x] I have run `Set-AVMModule` locally to generate the supporting module files. - [x] My corresponding pipelines / checks run clean and green without any errors or warnings --- avm/res/purview/account/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avm/res/purview/account/README.md b/avm/res/purview/account/README.md index 0630647d57..f9fe9be49a 100644 --- a/avm/res/purview/account/README.md +++ b/avm/res/purview/account/README.md @@ -1,7 +1,7 @@ # Purview Accounts `[Microsoft.Purview/accounts]` > ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ -> +> > - Only security and bug fixes are being handled by the AVM core team at present. > - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! From e91b62bfb6f6c1921adf3b53b7cc95f73542ccd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Barab=C3=A1s?= Date: Tue, 26 Mar 2024 11:07:06 -0700 Subject: [PATCH 68/73] chore: triage automation bug fixes (#1424) # Overview/Summary This PR fixes some bugs related to the latest issue triage automation improvements. ## As part of this Pull Request I have - [x] Read the Contribution Guide and ensured this PR is compliant with the guide - [x] Checked for duplicate [Pull Requests](https://github.com/Azure/Azure-Verified-Modules/pulls) - [ ] Associated it with relevant [GitHub Issues](https://github.com/Azure/Azure-Verified-Modules/issues) or ADO Work Items (Internal Only) - [x] Ensured my code/branch is up-to-date with the latest changes in the `main` [branch](https://github.com/Azure/Azure-Verified-Modules/) - [x] Ensured PR tests are passing - [x] Updated relevant and associated documentation (e.g. Contribution Guide, Docs etc.) --- .github/policies/eventResponder.yml | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/.github/policies/eventResponder.yml b/.github/policies/eventResponder.yml index b72029b8ea..97dcec2191 100644 --- a/.github/policies/eventResponder.yml +++ b/.github/policies/eventResponder.yml @@ -60,6 +60,9 @@ configuration: pattern: "AVM" - commentContains: pattern: "azure verified modules" + - not: + hasLabel: + label: "Type: AVM :a: :v: :m:" then: - addLabel: label: "Type: AVM :a: :v: :m:" @@ -75,6 +78,9 @@ configuration: - payloadType: Issue_Comment - commentContains: pattern: "#RR" + - not: + hasLabel: + label: "Needs: Author Feedback :ear:" then: - addLabel: label: "Needs: Author Feedback :ear:" @@ -90,6 +96,9 @@ configuration: - payloadType: Issue_Comment - commentContains: pattern: "#wontfix" + - not: + hasLabel: + label: "Status: Won't Fix :broken_heart:" then: - addLabel: label: "Status: Won't Fix :broken_heart:" @@ -128,6 +137,8 @@ configuration: - description: 'ITA15 - remove the "Needs: Triage" label from a PR, if it already has a "Type: XYZ" label added at the time of creating it.' if: - payloadType: Pull_Request + - isAction: + action: Opened - or: - hasLabel: label: "Type: Bug :bug:" @@ -145,10 +156,7 @@ configuration: label: "Type: Question/Feedback :raising_hand:" - hasLabel: label: "Type: Security Bug :lock:" - - hasLabel: - label: "Type: AVM :a: :v: :m:" - - isAction: - action: Opened + - isAssignedToSomeone then: - removeLabel: label: "Needs: Triage :mag:" @@ -167,6 +175,9 @@ configuration: ### Issue Type? Feature Request + - not: + hasLabel: + label: "Type: Feature Request :heavy_plus_sign:" then: - addLabel: label: "Type: Feature Request :heavy_plus_sign:" @@ -185,6 +196,9 @@ configuration: ### Issue Type? Bug + - not: + hasLabel: + label: "Type: Bug :bug:" then: - addLabel: label: "Type: Bug :bug:" @@ -203,6 +217,9 @@ configuration: ### Issue Type? Security Bug + - not: + hasLabel: + label: "Type: Security Bug :lock:" then: - addLabel: label: "Type: Security Bug :lock:" From d2ca86fa7aef2b9e5ba7049c04686f6edee70c5a Mon Sep 17 00:00:00 2001 From: hundredacres Date: Tue, 26 Mar 2024 12:02:41 -0700 Subject: [PATCH 69/73] fix: ALign default module to WAF-Aligned (#1425) ## Description Aligning default module config with WAF-Aligned. Fixes #1307 ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.db-for-my-sql.flexible-server](https://github.com/hundredacres/bicep-registry-modules/actions/workflows/avm.res.db-for-my-sql.flexible-server.yml/badge.svg?branch=db-for-my-sql_flexible-server_waf-aligned)](https://github.com/hundredacres/bicep-registry-modules/actions/workflows/avm.res.db-for-my-sql.flexible-server.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [ ] Azure Verified Module updates: - [ ] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [X] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [X] I'm sure there are no other open Pull Requests for the same update/change - [X] I have run `Set-AVMModule` locally to generate the supporting module files. - [X] My corresponding pipelines / checks run clean and green without any errors or warnings --- .../db-for-my-sql/flexible-server/README.md | 2 +- .../db-for-my-sql/flexible-server/main.bicep | 2 +- .../db-for-my-sql/flexible-server/main.json | 18 +++++++++--------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/avm/res/db-for-my-sql/flexible-server/README.md b/avm/res/db-for-my-sql/flexible-server/README.md index 8855bd9946..eab033d768 100644 --- a/avm/res/db-for-my-sql/flexible-server/README.md +++ b/avm/res/db-for-my-sql/flexible-server/README.md @@ -1093,7 +1093,7 @@ A value indicating whether Geo-Redundant backup is enabled on the server. If "En - Required: No - Type: string -- Default: `'Disabled'` +- Default: `'Enabled'` - Allowed: ```Bicep [ diff --git a/avm/res/db-for-my-sql/flexible-server/main.bicep b/avm/res/db-for-my-sql/flexible-server/main.bicep index a3aa0a019b..9d0bb2c610 100644 --- a/avm/res/db-for-my-sql/flexible-server/main.bicep +++ b/avm/res/db-for-my-sql/flexible-server/main.bicep @@ -54,7 +54,7 @@ param backupRetentionDays int = 7 'Enabled' ]) @description('Optional. A value indicating whether Geo-Redundant backup is enabled on the server. If "Enabled" and "cMKKeyName" is not empty, then "geoBackupCMKKeyVaultResourceId" and "cMKUserAssignedIdentityResourceId" are also required.') -param geoRedundantBackup string = 'Disabled' +param geoRedundantBackup string = 'Enabled' @allowed([ 'Default' diff --git a/avm/res/db-for-my-sql/flexible-server/main.json b/avm/res/db-for-my-sql/flexible-server/main.json index 2bb5f3d24a..64592c038c 100644 --- a/avm/res/db-for-my-sql/flexible-server/main.json +++ b/avm/res/db-for-my-sql/flexible-server/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "7560423312278776039" + "version": "0.26.54.24096", + "templateHash": "4782564139886750764" }, "name": "DBforMySQL Flexible Servers", "description": "This module deploys a DBforMySQL Flexible Server.", @@ -360,7 +360,7 @@ }, "geoRedundantBackup": { "type": "string", - "defaultValue": "Disabled", + "defaultValue": "Enabled", "allowedValues": [ "Disabled", "Enabled" @@ -799,8 +799,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "1786501395002693358" + "version": "0.26.54.24096", + "templateHash": "9734848552595709363" }, "name": "DBforMySQL Flexible Server Databases", "description": "This module deploys a DBforMySQL Flexible Server Database.", @@ -907,8 +907,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "1600222376229916804" + "version": "0.26.54.24096", + "templateHash": "2931317814738693960" }, "name": "DBforMySQL Flexible Server Firewall Rules", "description": "This module deploys a DBforMySQL Flexible Server Firewall Rule.", @@ -1014,8 +1014,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "9797360516324373554" + "version": "0.26.54.24096", + "templateHash": "2817201491275445304" }, "name": "DBforMySQL Flexible Server Administrators", "description": "This module deploys a DBforMySQL Flexible Server Administrator.", From b1ea42b883c0d6de54797342fe85634ae3b4d5b2 Mon Sep 17 00:00:00 2001 From: Alexander Sehr Date: Tue, 26 Mar 2024 22:31:38 +0100 Subject: [PATCH 70/73] feat: Re-formatted ALL AVM modules using the V2 formatter (#1368) ## Description - Re-formatted ALL AVM modules using the V2 formatter - Re-build ALL ARM JSON & Readme files - Removed V1 fallback bicep bicepconfig.json cc: @krbar ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.sql.server](https://github.com/AlexanderSehr/bicep-registry-modules/actions/workflows/avm.res.sql.server.yml/badge.svg?branch=users%2Falsehr%2FreformattedV2&event=workflow_dispatch)](https://github.com/AlexanderSehr/bicep-registry-modules/actions/workflows/avm.res.sql.server.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [ ] Azure Verified Module updates: - [ ] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation --------- Co-authored-by: Erika Gressi <56914614+eriqua@users.noreply.github.com> --- avm/bicepconfig.json | 3 +- avm/res/analysis-services/server/main.bicep | 134 ++-- avm/res/analysis-services/server/main.json | 4 +- .../server/tests/e2e/defaults/main.test.bicep | 16 +- .../server/tests/e2e/max/main.test.bicep | 135 ++-- .../tests/e2e/waf-aligned/main.test.bicep | 98 +-- .../service/api-version-set/main.json | 4 +- avm/res/api-management/service/api/main.json | 8 +- .../service/api/policy/main.json | 4 +- .../service/authorization-server/main.json | 4 +- .../api-management/service/backend/main.json | 4 +- .../api-management/service/cache/main.json | 4 +- .../service/identity-provider/main.json | 4 +- .../service/named-value/main.json | 4 +- .../api-management/service/policy/main.json | 4 +- .../service/portalsetting/main.json | 4 +- .../service/product/api/main.json | 4 +- .../service/product/group/main.json | 4 +- .../api-management/service/product/main.json | 12 +- .../service/subscription/main.json | 4 +- .../configuration-store/key-value/main.json | 4 +- .../configuration-store/main.bicep | 331 +++++---- .../configuration-store/main.json | 8 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../tests/e2e/encr/dependencies.bicep | 5 +- .../tests/e2e/encr/main.test.bicep | 66 +- .../tests/e2e/max/main.test.bicep | 145 ++-- .../tests/e2e/pe/main.test.bicep | 60 +- .../tests/e2e/waf-aligned/main.test.bicep | 60 +- .../automation-account/job-schedule/main.json | 4 +- .../automation/automation-account/main.bicep | 658 +++++++++++------- .../automation/automation-account/main.json | 32 +- .../automation-account/module/main.json | 4 +- .../automation-account/runbook/main.bicep | 27 +- .../automation-account/runbook/main.json | 4 +- .../automation-account/schedule/main.json | 4 +- .../software-update-configuration/main.bicep | 34 +- .../software-update-configuration/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../tests/e2e/encr/dependencies.bicep | 63 +- .../tests/e2e/encr/main.test.bicep | 40 +- .../tests/e2e/max/main.test.bicep | 413 +++++------ .../tests/e2e/waf-aligned/main.test.bicep | 352 +++++----- .../automation-account/variable/main.json | 4 +- avm/res/cdn/profile/afdEndpoint/main.bicep | 38 +- avm/res/cdn/profile/afdEndpoint/main.json | 8 +- .../cdn/profile/afdEndpoint/route/main.bicep | 35 +- .../cdn/profile/afdEndpoint/route/main.json | 4 +- avm/res/cdn/profile/customdomain/main.bicep | 31 +- avm/res/cdn/profile/customdomain/main.json | 4 +- avm/res/cdn/profile/endpoint/main.bicep | 36 +- avm/res/cdn/profile/endpoint/main.json | 8 +- .../cdn/profile/endpoint/origin/main.bicep | 38 +- avm/res/cdn/profile/endpoint/origin/main.json | 4 +- avm/res/cdn/profile/main.bicep | 263 ++++--- avm/res/cdn/profile/main.json | 44 +- avm/res/cdn/profile/origingroup/main.bicep | 34 +- avm/res/cdn/profile/origingroup/main.json | 8 +- .../cdn/profile/origingroup/origin/main.json | 4 +- avm/res/cdn/profile/ruleset/main.bicep | 24 +- avm/res/cdn/profile/ruleset/main.json | 8 +- avm/res/cdn/profile/ruleset/rule/main.json | 4 +- avm/res/cdn/profile/secret/main.bicep | 20 +- avm/res/cdn/profile/secret/main.json | 4 +- .../cdn/profile/tests/e2e/afd/main.test.bicep | 140 ++-- .../tests/e2e/defaults/main.test.bicep | 18 +- .../cdn/profile/tests/e2e/max/main.test.bicep | 117 ++-- .../tests/e2e/waf-aligned/main.test.bicep | 82 +-- avm/res/cognitive-services/account/main.bicep | 427 ++++++++---- avm/res/cognitive-services/account/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 18 +- .../account/tests/e2e/max/main.test.bicep | 213 +++--- .../account/tests/e2e/speech/main.test.bicep | 70 +- .../dependencies.bicep | 5 +- .../main.test.bicep | 42 +- .../dependencies.bicep | 5 +- .../main.test.bicep | 48 +- .../tests/e2e/waf-aligned/main.test.bicep | 88 +-- avm/res/compute/availability-set/main.bicep | 112 +-- avm/res/compute/availability-set/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../tests/e2e/max/dependencies.bicep | 8 +- .../tests/e2e/max/main.test.bicep | 67 +- .../tests/e2e/waf-aligned/dependencies.bicep | 4 +- .../tests/e2e/waf-aligned/main.test.bicep | 34 +- .../compute/disk-encryption-set/main.bicep | 158 +++-- avm/res/compute/disk-encryption-set/main.json | 12 +- .../e2e/accessPolicies/dependencies.bicep | 46 +- .../tests/e2e/accessPolicies/main.test.bicep | 79 ++- .../tests/e2e/defaults/dependencies.bicep | 40 +- .../tests/e2e/defaults/main.test.bicep | 26 +- .../tests/e2e/max/dependencies.bicep | 46 +- .../tests/e2e/max/main.test.bicep | 83 +-- .../tests/e2e/waf-aligned/dependencies.bicep | 46 +- .../tests/e2e/waf-aligned/main.test.bicep | 44 +- avm/res/compute/disk/main.bicep | 127 ++-- avm/res/compute/disk/main.json | 4 +- .../disk/tests/e2e/defaults/main.test.bicep | 20 +- .../disk/tests/e2e/image/dependencies.bicep | 4 +- .../disk/tests/e2e/image/main.test.bicep | 22 +- .../disk/tests/e2e/import/dependencies.bicep | 2 +- .../tests/e2e/import/dependencies_rbac.bicep | 5 +- .../disk/tests/e2e/import/main.test.bicep | 24 +- .../disk/tests/e2e/max/dependencies.bicep | 4 +- .../disk/tests/e2e/max/main.test.bicep | 79 ++- .../tests/e2e/waf-aligned/main.test.bicep | 46 +- .../compute/gallery/application/main.bicep | 45 +- avm/res/compute/gallery/application/main.json | 4 +- avm/res/compute/gallery/image/main.bicep | 63 +- avm/res/compute/gallery/image/main.json | 4 +- avm/res/compute/gallery/main.bicep | 189 ++--- avm/res/compute/gallery/main.json | 12 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../gallery/tests/e2e/max/dependencies.bicep | 4 +- .../gallery/tests/e2e/max/main.test.bicep | 251 +++---- .../tests/e2e/waf-aligned/dependencies.bicep | 4 +- .../tests/e2e/waf-aligned/main.test.bicep | 52 +- avm/res/compute/image/main.bicep | 99 +-- avm/res/compute/image/main.json | 4 +- .../tests/e2e/defaults/dependencies.bicep | 2 +- .../e2e/defaults/dependencies_rbac.bicep | 5 +- .../image/tests/e2e/defaults/main.test.bicep | 24 +- .../image/tests/e2e/max/dependencies.bicep | 7 +- .../tests/e2e/max/dependencies_rbac.bicep | 5 +- .../image/tests/e2e/max/main.test.bicep | 77 +- .../tests/e2e/waf-aligned/dependencies.bicep | 7 +- .../e2e/waf-aligned/dependencies_rbac.bicep | 5 +- .../tests/e2e/waf-aligned/main.test.bicep | 42 +- .../proximity-placement-group/main.bicep | 84 ++- .../proximity-placement-group/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../tests/e2e/max/dependencies.bicep | 4 +- .../tests/e2e/max/main.test.bicep | 95 +-- .../tests/e2e/waf-aligned/main.test.bicep | 54 +- avm/res/compute/ssh-public-key/main.bicep | 84 ++- avm/res/compute/ssh-public-key/main.json | 4 +- .../tests/e2e/max/dependencies.bicep | 57 +- .../tests/e2e/max/main.test.bicep | 5 +- .../tests/e2e/waf-aligned/dependencies.bicep | 57 +- .../tests/e2e/waf-aligned/main.test.bicep | 5 +- .../extension/main.json | 4 +- .../virtual-machine-scale-set/main.bicep | 653 ++++++++++------- .../virtual-machine-scale-set/main.json | 36 +- .../e2e/linux.defaults/dependencies.bicep | 5 +- .../tests/e2e/linux.defaults/main.test.bicep | 86 +-- .../tests/e2e/linux.max/dependencies.bicep | 10 +- .../tests/e2e/linux.max/main.test.bicep | 250 +++---- .../tests/e2e/linux.ssecmk/dependencies.bicep | 10 +- .../tests/e2e/linux.ssecmk/main.test.bicep | 108 +-- .../e2e/windows.defaults/main.test.bicep | 74 +- .../tests/e2e/windows.max/dependencies.bicep | 10 +- .../tests/e2e/windows.max/main.test.bicep | 242 +++---- .../windows.waf-aligned/dependencies.bicep | 10 +- .../e2e/windows.waf-aligned/main.test.bicep | 222 +++--- avm/res/consumption/budget/main.bicep | 67 +- avm/res/consumption/budget/main.json | 4 +- .../budget/tests/e2e/defaults/main.test.bicep | 22 +- .../budget/tests/e2e/max/main.test.bicep | 44 +- .../tests/e2e/waf-aligned/main.test.bicep | 36 +- .../registry/cache-rules/main.json | 4 +- .../container-registry/registry/main.bicep | 422 ++++++----- avm/res/container-registry/registry/main.json | 16 +- .../registry/replication/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../tests/e2e/encr/dependencies.bicep | 5 +- .../registry/tests/e2e/encr/main.test.bicep | 44 +- .../registry/tests/e2e/max/dependencies.bicep | 5 +- .../registry/tests/e2e/max/main.test.bicep | 215 +++--- .../tests/e2e/waf-aligned/dependencies.bicep | 5 +- .../tests/e2e/waf-aligned/main.test.bicep | 74 +- .../registry/webhook/main.json | 4 +- .../managed-cluster/agent-pool/main.bicep | 8 +- .../managed-cluster/agent-pool/main.json | 4 +- .../managed-cluster/main.bicep | 545 +++++++++------ .../managed-cluster/main.json | 8 +- .../tests/e2e/azure/dependencies.bicep | 17 +- .../tests/e2e/azure/main.test.bicep | 403 +++++------ .../tests/e2e/defaults/main.test.bicep | 36 +- .../tests/e2e/kubenet/dependencies.bicep | 8 +- .../tests/e2e/kubenet/main.test.bicep | 237 ++++--- .../tests/e2e/priv/dependencies.bicep | 10 +- .../tests/e2e/priv/main.test.bicep | 176 ++--- .../tests/e2e/waf-aligned/dependencies.bicep | 10 +- .../tests/e2e/waf-aligned/main.test.bicep | 258 +++---- .../backup-vault/backup-policy/main.json | 4 +- .../data-protection/backup-vault/main.bicep | 125 ++-- .../data-protection/backup-vault/main.json | 8 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../tests/e2e/max/dependencies.bicep | 4 +- .../tests/e2e/max/main.test.bicep | 187 ++--- .../tests/e2e/waf-aligned/main.test.bicep | 146 ++-- .../flexible-server/administrator/main.json | 4 +- .../flexible-server/database/main.json | 4 +- .../flexible-server/firewall-rule/main.json | 4 +- .../db-for-my-sql/flexible-server/main.bicep | 327 +++++---- .../tests/e2e/defaults/main.test.bicep | 24 +- .../tests/e2e/max/dependencies1.bicep | 53 +- .../tests/e2e/max/dependencies2.bicep | 126 ++-- .../tests/e2e/max/main.test.bicep | 206 +++--- .../tests/e2e/private/main.test.bicep | 73 +- .../tests/e2e/waf-aligned/main.test.bicep | 40 +- .../flexible-server/administrator/main.json | 4 +- .../flexible-server/configuration/main.json | 4 +- .../flexible-server/database/main.json | 4 +- .../flexible-server/firewall-rule/main.json | 4 +- .../application-group/application/main.json | 4 +- .../application-group/main.bicep | 144 ++-- .../application-group/main.json | 8 +- .../tests/e2e/defaults/main.test.bicep | 26 +- .../tests/e2e/max/main.test.bicep | 141 ++-- .../tests/e2e/waf-aligned/main.test.bicep | 48 +- .../host-pool/main.bicep | 197 +++--- .../host-pool/main.json | 4 +- .../host-pool/tests/e2e/max/main.test.bicep | 5 +- .../scaling-plan/main.bicep | 112 +-- .../scaling-plan/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../tests/e2e/max/main.test.bicep | 309 ++++---- .../tests/e2e/waf-aligned/main.test.bicep | 42 +- .../workspace/main.bicep | 197 +++--- .../workspace/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../workspace/tests/e2e/max/main.test.bicep | 235 ++++--- .../tests/e2e/waf-aligned/main.test.bicep | 44 +- .../dev-test-lab/lab/artifactsource/main.json | 4 +- avm/res/dev-test-lab/lab/cost/main.json | 4 +- avm/res/dev-test-lab/lab/main.bicep | 346 +++++---- avm/res/dev-test-lab/lab/main.json | 28 +- .../lab/notificationchannel/main.json | 4 +- .../lab/policyset/policy/main.json | 4 +- avm/res/dev-test-lab/lab/schedule/main.bicep | 10 +- avm/res/dev-test-lab/lab/schedule/main.json | 4 +- .../lab/tests/e2e/defaults/main.test.bicep | 16 +- .../lab/tests/e2e/max/dependencies.bicep | 5 +- .../lab/tests/e2e/max/main.test.bicep | 455 ++++++------ .../lab/tests/e2e/waf-aligned/main.test.bicep | 24 +- .../dev-test-lab/lab/virtualnetwork/main.json | 4 +- avm/res/event-grid/domain/main.bicep | 279 +++++--- avm/res/event-grid/domain/main.json | 8 +- .../domain/tests/e2e/defaults/main.test.bicep | 16 +- .../domain/tests/e2e/max/main.test.bicep | 153 ++-- .../tests/e2e/waf-aligned/main.test.bicep | 96 +-- avm/res/event-grid/domain/topic/main.json | 4 +- .../namespace/ca-certificate/main.json | 4 +- .../namespace/client-group/main.json | 4 +- .../event-grid/namespace/client/main.bicep | 19 +- avm/res/event-grid/namespace/client/main.json | 4 +- avm/res/event-grid/namespace/main.bicep | 467 ++++++++----- avm/res/event-grid/namespace/main.json | 32 +- .../namespace/permission-binding/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../tests/e2e/max/dependencies.bicep | 5 +- .../namespace/tests/e2e/max/main.test.bicep | 337 ++++----- .../tests/e2e/mqttct/dependencies.bicep | 5 +- .../tests/e2e/mqttct/main.test.bicep | 269 +++---- .../tests/e2e/mqttnt/main.test.bicep | 269 +++---- .../tests/e2e/waf-aligned/main.test.bicep | 111 +-- .../namespace/topic-space/main.bicep | 80 ++- .../namespace/topic-space/main.json | 4 +- .../topic/event-subscription/main.bicep | 80 ++- .../topic/event-subscription/main.json | 4 +- avm/res/event-grid/namespace/topic/main.bicep | 123 ++-- avm/res/event-grid/namespace/topic/main.json | 8 +- .../event-subscription/main.bicep | 14 +- .../system-topic/event-subscription/main.json | 4 +- avm/res/event-grid/system-topic/main.bicep | 219 +++--- avm/res/event-grid/system-topic/main.json | 8 +- .../tests/e2e/defaults/dependencies.bicep | 12 +- .../tests/e2e/defaults/main.test.bicep | 20 +- .../tests/e2e/max/dependencies.bicep | 30 +- .../tests/e2e/max/main.test.bicep | 141 ++-- .../tests/e2e/waf-aligned/dependencies.bicep | 22 +- .../tests/e2e/waf-aligned/main.test.bicep | 102 +-- .../topic/event-subscription/main.bicep | 16 +- .../topic/event-subscription/main.json | 4 +- avm/res/event-grid/topic/main.bicep | 305 ++++---- avm/res/event-grid/topic/main.json | 8 +- .../topic/tests/e2e/defaults/main.test.bicep | 16 +- .../topic/tests/e2e/max/main.test.bicep | 212 +++--- .../tests/e2e/waf-aligned/main.test.bicep | 132 ++-- .../namespace/authorization-rule/main.json | 4 +- .../disaster-recovery-config/main.json | 4 +- .../eventhub/authorization-rule/main.json | 4 +- .../eventhub/consumergroup/main.json | 4 +- .../event-hub/namespace/eventhub/main.bicep | 120 ++-- .../event-hub/namespace/eventhub/main.json | 12 +- avm/res/event-hub/namespace/main.bicep | 489 ++++++++----- avm/res/event-hub/namespace/main.json | 28 +- .../namespace/network-rule-set/main.bicep | 24 +- .../namespace/network-rule-set/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../tests/e2e/encr/dependencies.bicep | 5 +- .../namespace/tests/e2e/encr/main.test.bicep | 1 - .../namespace/tests/e2e/max/main.test.bicep | 317 ++++----- .../tests/e2e/waf-aligned/main.test.bicep | 238 +++---- avm/res/health-bot/health-bot/main.bicep | 102 +-- avm/res/health-bot/health-bot/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 18 +- .../tests/e2e/max/dependencies.bicep | 4 +- .../health-bot/tests/e2e/max/main.test.bicep | 81 ++- .../tests/e2e/waf-aligned/main.test.bicep | 34 +- avm/res/insights/action-group/main.bicep | 67 +- avm/res/insights/action-group/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 18 +- .../tests/e2e/max/dependencies.bicep | 4 +- .../tests/e2e/max/main.test.bicep | 99 +-- .../tests/e2e/waf-aligned/dependencies.bicep | 4 +- .../tests/e2e/waf-aligned/main.test.bicep | 26 +- .../insights/activity-log-alert/main.bicep | 77 +- avm/res/insights/activity-log-alert/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 76 +- .../tests/e2e/max/main.test.bicep | 139 ++-- .../tests/e2e/waf-aligned/main.test.bicep | 102 +-- .../component/linkedStorageAccounts/main.json | 4 +- avm/res/insights/component/main.bicep | 130 ++-- avm/res/insights/component/main.json | 8 +- .../tests/e2e/defaults/dependencies.bicep | 4 +- .../component/tests/e2e/max/main.test.bicep | 5 +- .../tests/e2e/waf-aligned/dependencies.bicep | 4 +- .../data-collection-endpoint/main.bicep | 84 ++- .../data-collection-endpoint/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../tests/e2e/max/main.test.bicep | 69 +- .../tests/e2e/waf-aligned/main.test.bicep | 26 +- .../insights/data-collection-rule/main.bicep | 84 ++- .../insights/data-collection-rule/main.json | 4 +- .../tests/e2e/customadv/dependencies.bicep | 82 +-- .../tests/e2e/customadv/main.test.bicep | 142 ++-- .../tests/e2e/custombasic/dependencies.bicep | 50 +- .../tests/e2e/custombasic/main.test.bicep | 110 +-- .../tests/e2e/customiis/dependencies.bicep | 18 +- .../tests/e2e/customiis/main.test.bicep | 80 +-- .../tests/e2e/defaults/main.test.bicep | 78 ++- .../tests/e2e/linux/dependencies.bicep | 4 +- .../tests/e2e/linux/main.test.bicep | 295 ++++---- .../tests/e2e/max/dependencies.bicep | 54 +- .../tests/e2e/max/main.test.bicep | 151 ++-- .../tests/e2e/waf-aligned/dependencies.bicep | 4 +- .../tests/e2e/waf-aligned/main.test.bicep | 203 +++--- .../tests/e2e/windows/dependencies.bicep | 4 +- .../tests/e2e/windows/main.test.bicep | 203 +++--- .../insights/diagnostic-setting/main.bicep | 53 +- avm/res/insights/diagnostic-setting/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../tests/e2e/max/main.test.bicep | 32 +- .../tests/e2e/waf-aligned/main.test.bicep | 32 +- avm/res/insights/metric-alert/main.bicep | 77 +- avm/res/insights/metric-alert/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 42 +- .../tests/e2e/max/dependencies.bicep | 16 +- .../tests/e2e/max/main.test.bicep | 95 +-- .../tests/e2e/waf-aligned/dependencies.bicep | 12 +- .../tests/e2e/waf-aligned/main.test.bicep | 58 +- .../insights/private-link-scope/main.bicep | 249 ++++--- avm/res/insights/private-link-scope/main.json | 8 +- .../scoped-resource/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../tests/e2e/max/main.test.bicep | 299 ++++---- .../tests/e2e/waf-aligned/main.test.bicep | 226 +++--- .../insights/scheduled-query-rule/main.bicep | 67 +- .../insights/scheduled-query-rule/main.json | 4 +- .../tests/e2e/defaults/dependencies.bicep | 4 +- .../tests/e2e/defaults/main.test.bicep | 76 +- .../tests/e2e/max/dependencies.bicep | 8 +- .../tests/e2e/max/main.test.bicep | 125 ++-- .../tests/e2e/waf-aligned/dependencies.bicep | 4 +- .../tests/e2e/waf-aligned/main.test.bicep | 94 +-- avm/res/insights/webtest/main.bicep | 84 ++- avm/res/insights/webtest/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 26 +- .../webtest/tests/e2e/max/main.test.bicep | 87 +-- .../tests/e2e/waf-aligned/main.test.bicep | 42 +- .../extension/main.bicep | 81 ++- .../extension/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 30 +- .../extension/tests/e2e/max/main.test.bicep | 80 +-- .../tests/e2e/waf-aligned/main.test.bicep | 80 +-- .../flux-configuration/main.bicep | 27 +- .../flux-configuration/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 52 +- .../tests/e2e/max/main.test.bicep | 70 +- .../tests/e2e/waf-aligned/main.test.bicep | 62 +- .../workspace/compute/main.bicep | 70 +- .../workspace/compute/main.json | 4 +- .../workspace/main.bicep | 375 ++++++---- .../workspace/main.json | 8 +- .../tests/e2e/defaults/dependencies.bicep | 48 +- .../tests/e2e/defaults/main.test.bicep | 30 +- .../tests/e2e/encr/dependencies.bicep | 10 +- .../workspace/tests/e2e/encr/main.test.bicep | 52 +- .../tests/e2e/max/dependencies.bicep | 10 +- .../workspace/tests/e2e/max/main.test.bicep | 211 +++--- .../tests/e2e/waf-aligned/dependencies.bicep | 10 +- .../tests/e2e/waf-aligned/main.test.bicep | 78 ++- .../maintenance-configuration/main.bicep | 89 ++- .../maintenance-configuration/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../tests/e2e/max/dependencies.bicep | 4 +- .../tests/e2e/max/main.test.bicep | 117 ++-- .../tests/e2e/waf-aligned/main.test.bicep | 78 ++- .../federated-identity-credential/main.json | 4 +- .../user-assigned-identity/main.bicep | 116 +-- .../user-assigned-identity/main.json | 8 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../tests/e2e/max/dependencies.bicep | 4 +- .../tests/e2e/max/main.test.bicep | 85 +-- .../tests/e2e/waf-aligned/dependencies.bicep | 4 +- .../tests/e2e/waf-aligned/main.test.bicep | 50 +- .../management/management-group/main.bicep | 41 +- avm/res/management/management-group/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 14 +- .../tests/e2e/max/main.test.bicep | 18 +- .../tests/e2e/waf-aligned/main.test.bicep | 18 +- .../application-security-group/main.bicep | 84 ++- .../application-security-group/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../tests/e2e/max/dependencies.bicep | 4 +- .../tests/e2e/max/main.test.bicep | 65 +- .../tests/e2e/waf-aligned/main.test.bicep | 32 +- avm/res/network/azure-firewall/main.bicep | 361 ++++++---- avm/res/network/azure-firewall/main.json | 4 +- .../tests/e2e/addpip/main.test.bicep | 44 +- .../tests/e2e/custompip/main.test.bicep | 72 +- .../tests/e2e/defaults/main.test.bicep | 18 +- .../tests/e2e/hubcommon/main.test.bicep | 26 +- .../tests/e2e/hubmin/main.test.bicep | 24 +- .../tests/e2e/max/main.test.bicep | 255 +++---- .../tests/e2e/waf-aligned/main.test.bicep | 212 +++--- avm/res/network/bastion-host/main.bicep | 196 +++--- avm/res/network/bastion-host/main.json | 4 +- .../tests/e2e/custompip/main.test.bicep | 96 +-- .../tests/e2e/defaults/main.test.bicep | 24 +- .../tests/e2e/max/main.test.bicep | 107 +-- .../tests/e2e/waf-aligned/main.test.bicep | 64 +- avm/res/network/connection/main.bicep | 70 +- avm/res/network/connection/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 36 +- .../connection/tests/e2e/max/main.test.bicep | 60 +- .../tests/e2e/waf-aligned/main.test.bicep | 54 +- .../network/ddos-protection-plan/main.bicep | 84 ++- .../network/ddos-protection-plan/main.json | 4 +- .../tests/e2e/max/dependencies.bicep | 4 +- .../tests/e2e/max/main.test.bicep | 5 +- .../forwarding-rule/main.json | 4 +- .../network/dns-forwarding-ruleset/main.bicep | 147 ++-- .../network/dns-forwarding-ruleset/main.json | 12 +- .../tests/e2e/defaults/dependencies.bicep | 7 +- .../tests/e2e/defaults/main.test.bicep | 26 +- .../tests/e2e/max/dependencies.bicep | 8 +- .../tests/e2e/max/main.test.bicep | 109 +-- .../tests/e2e/waf-aligned/dependencies.bicep | 8 +- .../tests/e2e/waf-aligned/main.test.bicep | 44 +- .../virtual-network-link/main.json | 4 +- .../dns-resolver/inbound-endpoint/main.json | 4 +- avm/res/network/dns-resolver/main.bicep | 157 +++-- avm/res/network/dns-resolver/main.json | 12 +- .../dns-resolver/outbound-endpoint/main.json | 4 +- .../tests/e2e/defaults/dependencies.bicep | 7 +- .../tests/e2e/defaults/main.test.bicep | 18 +- .../tests/e2e/max/dependencies.bicep | 7 +- .../tests/e2e/max/main.test.bicep | 91 +-- .../tests/e2e/waf-aligned/dependencies.bicep | 7 +- .../tests/e2e/waf-aligned/main.test.bicep | 54 +- avm/res/network/dns-zone/a/main.bicep | 78 ++- avm/res/network/dns-zone/a/main.json | 4 +- avm/res/network/dns-zone/aaaa/main.bicep | 78 ++- avm/res/network/dns-zone/aaaa/main.json | 4 +- avm/res/network/dns-zone/caa/main.bicep | 70 +- avm/res/network/dns-zone/caa/main.json | 4 +- avm/res/network/dns-zone/cname/main.bicep | 78 ++- avm/res/network/dns-zone/cname/main.json | 4 +- avm/res/network/dns-zone/main.bicep | 360 ++++++---- avm/res/network/dns-zone/main.json | 44 +- avm/res/network/dns-zone/mx/main.bicep | 70 +- avm/res/network/dns-zone/mx/main.json | 4 +- avm/res/network/dns-zone/ns/main.bicep | 70 +- avm/res/network/dns-zone/ns/main.json | 4 +- avm/res/network/dns-zone/ptr/main.bicep | 70 +- avm/res/network/dns-zone/ptr/main.json | 4 +- avm/res/network/dns-zone/soa/main.bicep | 70 +- avm/res/network/dns-zone/soa/main.json | 4 +- avm/res/network/dns-zone/srv/main.bicep | 70 +- avm/res/network/dns-zone/srv/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../dns-zone/tests/e2e/max/dependencies.bicep | 32 +- .../dns-zone/tests/e2e/max/main.test.bicep | 516 +++++++------- .../tests/e2e/waf-aligned/dependencies.bicep | 32 +- .../tests/e2e/waf-aligned/main.test.bicep | 32 +- avm/res/network/dns-zone/txt/main.bicep | 70 +- avm/res/network/dns-zone/txt/main.json | 4 +- .../network/express-route-circuit/main.bicep | 175 +++-- .../network/express-route-circuit/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 22 +- .../tests/e2e/max/dependencies.bicep | 4 +- .../tests/e2e/max/main.test.bicep | 107 +-- .../tests/e2e/waf-aligned/dependencies.bicep | 4 +- .../tests/e2e/waf-aligned/main.test.bicep | 70 +- .../network/express-route-gateway/main.bicep | 89 ++- .../network/express-route-gateway/main.json | 4 +- .../tests/e2e/max/main.test.bicep | 5 +- avm/res/network/firewall-policy/main.bicep | 143 ++-- avm/res/network/firewall-policy/main.json | 8 +- .../rule-collection-group/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../tests/e2e/max/main.test.bicep | 112 +-- .../tests/e2e/waf-aligned/main.test.bicep | 102 +-- .../main.bicep | 86 ++- .../main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../tests/e2e/max/main.test.bicep | 185 ++--- .../tests/e2e/waf-aligned/main.test.bicep | 150 ++-- avm/res/network/front-door/main.bicep | 139 ++-- avm/res/network/front-door/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 156 +++-- .../tests/e2e/max/dependencies.bicep | 4 +- .../front-door/tests/e2e/max/main.test.bicep | 255 +++---- .../tests/e2e/waf-aligned/main.test.bicep | 196 +++--- avm/res/network/ip-group/main.bicep | 89 ++- avm/res/network/ip-group/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../ip-group/tests/e2e/max/dependencies.bicep | 4 +- .../ip-group/tests/e2e/max/main.test.bicep | 73 +- .../tests/e2e/waf-aligned/main.test.bicep | 32 +- .../backend-address-pool/main.json | 4 +- .../load-balancer/inbound-nat-rule/main.bicep | 8 +- .../load-balancer/inbound-nat-rule/main.json | 4 +- avm/res/network/load-balancer/main.bicep | 383 ++++++---- avm/res/network/load-balancer/main.json | 12 +- .../tests/e2e/defaults/main.test.bicep | 38 +- .../tests/e2e/internal/main.test.bicep | 175 ++--- .../tests/e2e/max/main.test.bicep | 259 +++---- .../tests/e2e/waf-aligned/main.test.bicep | 261 +++---- .../network/local-network-gateway/main.bicep | 92 ++- .../network/local-network-gateway/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 24 +- .../tests/e2e/max/dependencies.bicep | 4 +- .../tests/e2e/max/main.test.bicep | 77 +- .../tests/e2e/waf-aligned/main.test.bicep | 44 +- avm/res/network/nat-gateway/main.bicep | 169 +++-- avm/res/network/nat-gateway/main.json | 12 +- .../tests/e2e/defaults/main.test.bicep | 18 +- .../tests/e2e/max/dependencies.bicep | 4 +- .../nat-gateway/tests/e2e/max/main.test.bicep | 152 ++-- .../tests/e2e/prefixCombined/main.test.bicep | 32 +- .../tests/e2e/waf-aligned/main.test.bicep | 80 +-- avm/res/network/network-interface/main.bicep | 215 +++--- avm/res/network/network-interface/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 32 +- .../tests/e2e/max/main.test.bicep | 137 ++-- .../tests/e2e/waf-aligned/main.test.bicep | 96 +-- .../connectivity-configuration/main.json | 4 +- avm/res/network/network-manager/main.bicep | 202 +++--- avm/res/network/network-manager/main.json | 32 +- .../network-manager/network-group/main.bicep | 18 +- .../network-manager/network-group/main.json | 8 +- .../network-group/static-member/main.json | 4 +- .../scope-connection/main.json | 4 +- .../security-admin-configuration/main.bicep | 22 +- .../security-admin-configuration/main.json | 12 +- .../rule-collection/main.bicep | 36 +- .../rule-collection/main.json | 8 +- .../rule-collection/rule/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 28 +- .../tests/e2e/max/main.test.bicep | 419 +++++------ .../tests/e2e/waf-aligned/main.test.bicep | 38 +- .../network/network-security-group/main.bicep | 256 ++++--- .../network/network-security-group/main.json | 8 +- .../security-rule/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../tests/e2e/max/main.test.bicep | 213 +++--- .../tests/e2e/waf-aligned/main.test.bicep | 176 ++--- avm/res/network/private-dns-zone/a/main.bicep | 50 +- avm/res/network/private-dns-zone/a/main.json | 4 +- .../network/private-dns-zone/aaaa/main.bicep | 50 +- .../network/private-dns-zone/aaaa/main.json | 4 +- .../network/private-dns-zone/cname/main.bicep | 50 +- .../network/private-dns-zone/cname/main.json | 4 +- avm/res/network/private-dns-zone/main.bicep | 305 ++++---- avm/res/network/private-dns-zone/main.json | 40 +- .../network/private-dns-zone/mx/main.bicep | 50 +- avm/res/network/private-dns-zone/mx/main.json | 4 +- .../network/private-dns-zone/ptr/main.bicep | 50 +- .../network/private-dns-zone/ptr/main.json | 4 +- .../network/private-dns-zone/soa/main.bicep | 50 +- .../network/private-dns-zone/soa/main.json | 4 +- .../network/private-dns-zone/srv/main.bicep | 50 +- .../network/private-dns-zone/srv/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../tests/e2e/max/main.test.bicep | 520 +++++++------- .../tests/e2e/waf-aligned/main.test.bicep | 32 +- .../network/private-dns-zone/txt/main.bicep | 50 +- .../network/private-dns-zone/txt/main.json | 4 +- .../virtual-network-link/main.json | 4 +- avm/res/network/private-endpoint/main.bicep | 136 ++-- avm/res/network/private-endpoint/main.json | 8 +- .../private-dns-zone-group/main.bicep | 12 +- .../private-dns-zone-group/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 60 +- .../tests/e2e/max/main.test.bicep | 143 ++-- .../tests/e2e/waf-aligned/main.test.bicep | 94 +-- .../network/private-link-service/main.bicep | 94 ++- .../network/private-link-service/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 42 +- .../tests/e2e/max/main.test.bicep | 119 ++-- .../tests/e2e/waf-aligned/main.test.bicep | 78 ++- avm/res/network/public-ip-address/main.bicep | 165 +++-- .../tests/e2e/defaults/main.test.bicep | 16 +- .../tests/e2e/max/main.test.bicep | 107 +-- .../tests/e2e/waf-aligned/main.test.bicep | 107 +-- avm/res/network/public-ip-prefix/main.bicep | 89 ++- avm/res/network/public-ip-prefix/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 18 +- .../tests/e2e/max/dependencies.bicep | 4 +- .../tests/e2e/max/main.test.bicep | 67 +- .../tests/e2e/waf-aligned/dependencies.bicep | 4 +- .../tests/e2e/waf-aligned/main.test.bicep | 26 +- avm/res/network/route-table/main.bicep | 92 ++- avm/res/network/route-table/main.json | 4 +- .../tests/e2e/max/dependencies.bicep | 4 +- .../route-table/tests/e2e/max/main.test.bicep | 5 +- .../network/trafficmanagerprofile/main.bicep | 144 ++-- .../network/trafficmanagerprofile/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../tests/e2e/max/main.test.bicep | 95 +-- .../tests/e2e/waf-aligned/main.test.bicep | 112 +-- .../virtual-hub/hub-route-table/main.bicep | 27 +- .../virtual-hub/hub-route-table/main.json | 4 +- .../hub-virtual-network-connection/main.bicep | 27 +- .../hub-virtual-network-connection/main.json | 4 +- avm/res/network/virtual-hub/main.bicep | 149 ++-- avm/res/network/virtual-hub/main.json | 12 +- .../tests/e2e/defaults/main.test.bicep | 21 +- .../tests/e2e/max/dependencies.bicep | 1 - .../virtual-hub/tests/e2e/max/main.test.bicep | 80 +-- .../tests/e2e/waf-aligned/dependencies.bicep | 1 - .../tests/e2e/waf-aligned/main.test.bicep | 80 +-- .../virtual-network-gateway/main.bicep | 366 +++++----- .../network/virtual-network-gateway/main.json | 8 +- .../nat-rule/main.json | 4 +- .../tests/e2e/aadvpn/main.test.bicep | 66 +- .../tests/e2e/defaults/main.test.bicep | 36 +- .../tests/e2e/expressRoute/main.test.bicep | 44 +- .../tests/e2e/max/main.test.bicep | 205 +++--- .../tests/e2e/vpn/main.test.bicep | 58 +- .../tests/e2e/waf-aligned/main.test.bicep | 170 ++--- avm/res/network/virtual-network/main.bicep | 347 +++++---- avm/res/network/virtual-network/main.json | 16 +- .../network/virtual-network/subnet/main.bicep | 71 +- .../network/virtual-network/subnet/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 22 +- .../tests/e2e/max/main.test.bicep | 204 +++--- .../tests/e2e/vnetPeering/main.test.bicep | 90 +-- .../tests/e2e/waf-aligned/main.test.bicep | 190 ++--- .../virtual-network-peering/main.json | 4 +- avm/res/network/virtual-wan/main.bicep | 89 ++- avm/res/network/virtual-wan/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../tests/e2e/max/dependencies.bicep | 4 +- .../virtual-wan/tests/e2e/max/main.test.bicep | 79 ++- .../tests/e2e/waf-aligned/dependencies.bicep | 4 +- .../tests/e2e/waf-aligned/main.test.bicep | 38 +- avm/res/network/vpn-gateway/main.bicep | 157 +++-- avm/res/network/vpn-gateway/main.json | 12 +- .../network/vpn-gateway/nat-rule/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 24 +- .../vpn-gateway/tests/e2e/max/main.test.bicep | 106 +-- .../tests/e2e/waf-aligned/main.test.bicep | 106 +-- .../vpn-gateway/vpn-connection/main.bicep | 8 +- .../vpn-gateway/vpn-connection/main.json | 4 +- avm/res/network/vpn-site/main.bicep | 100 ++- avm/res/network/vpn-site/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 30 +- .../vpn-site/tests/e2e/max/main.test.bicep | 145 ++-- .../tests/e2e/waf-aligned/main.test.bicep | 110 +-- .../workspace/data-export/main.json | 4 +- .../workspace/data-source/main.bicep | 20 +- .../workspace/data-source/main.json | 4 +- .../workspace/linked-service/main.json | 4 +- .../linked-storage-account/main.json | 4 +- .../operational-insights/workspace/main.bicep | 394 ++++++----- .../operational-insights/workspace/main.json | 32 +- .../workspace/saved-search/main.json | 4 +- .../storage-insight-config/main.json | 4 +- .../workspace/table/main.bicep | 60 +- .../workspace/table/main.json | 4 +- .../workspace/tests/e2e/adv/main.test.bicep | 508 +++++++------- .../tests/e2e/defaults/main.test.bicep | 16 +- .../workspace/tests/e2e/max/main.test.bicep | 521 +++++++------- .../tests/e2e/waf-aligned/main.test.bicep | 298 ++++---- .../operations-management/solution/main.bicep | 27 +- .../operations-management/solution/main.json | 4 +- .../tests/e2e/waf-aligned/main.test.bicep | 22 +- .../power-bi-dedicated/capacity/main.bicep | 94 ++- avm/res/power-bi-dedicated/capacity/main.json | 4 +- .../tests/e2e/defaults/dependencies.bicep | 4 +- .../tests/e2e/defaults/main.test.bicep | 26 +- .../capacity/tests/e2e/max/dependencies.bicep | 4 +- .../capacity/tests/e2e/max/main.test.bicep | 81 ++- .../tests/e2e/waf-aligned/dependencies.bicep | 4 +- .../tests/e2e/waf-aligned/main.test.bicep | 44 +- avm/res/purview/account/main.bicep | 578 ++++++++------- avm/res/purview/account/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../account/tests/e2e/max/dependencies.bicep | 10 +- .../account/tests/e2e/max/main.test.bicep | 267 +++---- .../tests/e2e/waf-aligned/dependencies.bicep | 10 +- .../tests/e2e/waf-aligned/main.test.bicep | 141 ++-- .../vault/backup-config/main.json | 4 +- .../protection-container/main.bicep | 24 +- .../protection-container/main.json | 8 +- .../protected-item/main.json | 4 +- .../vault/backup-policy/main.json | 4 +- .../vault/backup-storage-config/main.json | 4 +- avm/res/recovery-services/vault/main.bicep | 447 +++++++----- avm/res/recovery-services/vault/main.json | 44 +- .../vault/replication-alert-setting/main.json | 4 +- .../vault/replication-fabric/main.bicep | 26 +- .../vault/replication-fabric/main.json | 12 +- .../main.bicep | 38 +- .../main.json | 8 +- .../main.bicep | 17 +- .../main.json | 4 +- .../vault/replication-policy/main.json | 4 +- .../vault/tests/e2e/defaults/main.test.bicep | 38 +- .../vault/tests/e2e/dr/main.test.bicep | 134 ++-- .../vault/tests/e2e/max/main.test.bicep | 619 ++++++++-------- .../tests/e2e/waf-aligned/main.test.bicep | 582 ++++++++-------- avm/res/resource-graph/query/main.bicep | 84 ++- avm/res/resource-graph/query/main.json | 4 +- .../query/tests/e2e/max/main.test.bicep | 5 +- .../resources/deployment-script/main.bicep | 134 ++-- avm/res/resources/deployment-script/main.json | 4 +- .../tests/e2e/max/main.test.bicep | 5 +- avm/res/resources/resource-group/main.bicep | 57 +- avm/res/resources/resource-group/main.json | 12 +- .../tests/e2e/defaults/main.test.bicep | 14 +- .../tests/e2e/max/main.test.bicep | 5 +- avm/res/search/search-service/main.bicep | 267 ++++--- avm/res/search/search-service/main.json | 8 +- .../shared-private-link-resource/main.json | 4 +- .../tests/e2e/max/main.test.bicep | 5 +- .../namespace/authorization-rule/main.json | 4 +- .../disaster-recovery-config/main.json | 4 +- avm/res/service-bus/namespace/main.bicep | 526 ++++++++------ avm/res/service-bus/namespace/main.json | 40 +- .../migration-configuration/main.json | 4 +- .../namespace/network-rule-set/main.bicep | 22 +- .../namespace/network-rule-set/main.json | 4 +- .../queue/authorization-rule/main.json | 4 +- .../service-bus/namespace/queue/main.bicep | 90 ++- avm/res/service-bus/namespace/queue/main.json | 8 +- .../tests/e2e/defaults/main.test.bicep | 20 +- .../tests/e2e/encr/dependencies.bicep | 5 +- .../namespace/tests/e2e/encr/main.test.bicep | 50 +- .../namespace/tests/e2e/max/main.test.bicep | 366 +++++----- .../tests/e2e/waf-aligned/main.test.bicep | 260 +++---- .../topic/authorization-rule/main.json | 4 +- .../service-bus/namespace/topic/main.bicep | 162 +++-- avm/res/service-bus/namespace/topic/main.json | 12 +- .../namespace/topic/subscription/main.json | 4 +- avm/res/signal-r-service/signal-r/main.bicep | 254 ++++--- avm/res/signal-r-service/signal-r/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../signal-r/tests/e2e/max/main.test.bicep | 156 +++-- .../tests/e2e/waf-aligned/main.test.bicep | 99 +-- .../signal-r-service/web-pub-sub/main.bicep | 244 ++++--- .../signal-r-service/web-pub-sub/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../web-pub-sub/tests/e2e/max/main.test.bicep | 153 ++-- .../tests/e2e/waf-aligned/main.test.bicep | 98 +-- .../main.json | 4 +- .../main.json | 4 +- avm/res/sql/server/database/main.bicep | 97 ++- avm/res/sql/server/database/main.json | 12 +- avm/res/sql/server/elastic-pool/main.json | 4 +- .../sql/server/encryption-protector/main.json | 4 +- avm/res/sql/server/firewall-rule/main.json | 4 +- avm/res/sql/server/key/main.bicep | 4 +- avm/res/sql/server/key/main.json | 4 +- avm/res/sql/server/main.bicep | 554 +++++++++------ avm/res/sql/server/main.json | 48 +- .../server/security-alert-policy/main.json | 4 +- .../server/tests/e2e/defaults/main.test.bicep | 20 +- .../server/tests/e2e/max/dependencies.bicep | 12 +- .../sql/server/tests/e2e/max/main.test.bicep | 5 +- .../tests/e2e/waf-aligned/dependencies.bicep | 12 +- .../sql/server/virtual-network-rule/main.json | 4 +- .../vulnerability-assessment/main.bicep | 19 +- .../server/vulnerability-assessment/main.json | 8 +- .../container/immutability-policy/main.json | 4 +- .../blob-service/container/main.json | 8 +- .../storage-account/blob-service/main.json | 12 +- .../storage-account/file-service/main.json | 12 +- .../file-service/share/main.json | 8 +- .../storage-account/local-user/main.json | 4 +- avm/res/storage/storage-account/main.bicep | 594 ++++++++++------ .../management-policy/main.json | 4 +- .../storage-account/queue-service/main.json | 8 +- .../queue-service/queue/main.json | 4 +- .../storage-account/table-service/main.json | 8 +- .../table-service/table/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 21 +- avm/res/synapse/private-link-hub/main.bicep | 170 +++-- avm/res/synapse/private-link-hub/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../tests/e2e/max/main.test.bicep | 96 +-- .../tests/e2e/waf-aligned/dependencies.bicep | 1 - .../tests/e2e/waf-aligned/main.test.bicep | 54 +- .../workspace/integration-runtime/main.bicep | 22 +- .../workspace/integration-runtime/main.json | 4 +- avm/res/synapse/workspace/key/main.json | 4 +- avm/res/synapse/workspace/main.bicep | 377 ++++++---- avm/res/synapse/workspace/main.json | 16 +- .../tests/e2e/defaults/dependencies.bicep | 28 +- .../tests/e2e/defaults/main.test.bicep | 28 +- .../tests/e2e/encrwsai/dependencies.bicep | 68 +- .../tests/e2e/encrwsai/main.test.bicep | 36 +- .../tests/e2e/encrwuai/dependencies.bicep | 89 +-- .../tests/e2e/encrwuai/main.test.bicep | 36 +- .../tests/e2e/managedvnet/dependencies.bicep | 28 +- .../tests/e2e/managedvnet/main.test.bicep | 36 +- .../workspace/tests/e2e/max/main.test.bicep | 203 +++--- .../tests/e2e/waf-aligned/main.test.bicep | 110 +-- .../image-template/main.bicep | 174 +++-- .../image-template/main.json | 4 +- .../tests/e2e/defaults/dependencies.bicep | 5 +- .../tests/e2e/max/dependencies.bicep | 22 +- .../tests/e2e/max/main.test.bicep | 5 +- avm/res/web/serverfarm/main.bicep | 145 ++-- avm/res/web/serverfarm/main.json | 4 +- .../tests/e2e/defaults/main.test.bicep | 28 +- .../serverfarm/tests/e2e/max/main.test.bicep | 113 +-- .../tests/e2e/waf-aligned/main.test.bicep | 78 ++- avm/res/web/site/README.md | 5 +- .../web/site/config--appsettings/main.bicep | 49 +- .../relay/main.bicep | 8 +- avm/res/web/site/main.bicep | 439 +++++++----- .../site/slot/config--appsettings/main.bicep | 47 +- .../relay/main.bicep | 8 +- avm/res/web/site/slot/main.bicep | 314 +++++---- .../functionApp.defaults/dependencies.bicep | 20 +- .../e2e/functionApp.defaults/main.test.bicep | 30 +- .../tests/e2e/functionApp.max/main.test.bicep | 295 ++++---- .../tests/e2e/waf-aligned/main.test.bicep | 84 +-- .../e2e/webApp.defaults/dependencies.bicep | 20 +- .../tests/e2e/webApp.defaults/main.test.bicep | 34 +- .../site/tests/e2e/webApp.max/main.test.bicep | 351 +++++----- .../webAppLinux.defaults/dependencies.bicep | 24 +- .../e2e/webAppLinux.defaults/main.test.bicep | 26 +- .../tests/e2e/webAppLinux.max/main.test.bicep | 351 +++++----- avm/res/web/static-site/config/main.json | 4 +- .../web/static-site/custom-domain/main.json | 4 +- .../web/static-site/linked-backend/main.json | 4 +- avm/res/web/static-site/main.bicep | 265 ++++--- avm/res/web/static-site/main.json | 20 +- .../tests/e2e/defaults/main.test.bicep | 16 +- .../static-site/tests/e2e/max/main.test.bicep | 143 ++-- .../tests/e2e/waf-aligned/main.test.bicep | 90 +-- avm/utilities/tools/helper/src/src.main.bicep | 27 +- .../tools/helper/src/src.main.test.bicep | 18 +- 860 files changed, 32708 insertions(+), 26454 deletions(-) diff --git a/avm/bicepconfig.json b/avm/bicepconfig.json index 439facdc5b..6b8310f4d8 100644 --- a/avm/bicepconfig.json +++ b/avm/bicepconfig.json @@ -2,8 +2,7 @@ // For further information, please refer to the official documentation at: https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/bicep-config { "experimentalFeaturesEnabled": { - "publishSource": true, - "legacyFormatter": true // Reason: Enables code formatting with the v1 formatter, ensuring a safer transition to the v2 formatter + "publishSource": true }, "analyzers": { "core": { diff --git a/avm/res/analysis-services/server/main.bicep b/avm/res/analysis-services/server/main.bicep index 17aca5df92..0655bf5d17 100644 --- a/avm/res/analysis-services/server/main.bicep +++ b/avm/res/analysis-services/server/main.bicep @@ -45,27 +45,34 @@ 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.analysisservices-server.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.analysisservices-server.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource server 'Microsoft.AnalysisServices/servers@2017-08-01' = { name: name @@ -80,51 +87,66 @@ resource server 'Microsoft.AnalysisServices/servers@2017-08-01' = { } } -resource server_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.' +resource server_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: server } - scope: server -} -resource server_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource server_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: server } - scope: server -}] - -resource server_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(server.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +] + +resource server_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(server.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: server } - scope: server -}] +] @description('The name of the analysis service.') output name string = server.name diff --git a/avm/res/analysis-services/server/main.json b/avm/res/analysis-services/server/main.json index f5beb4b850..499b9433a1 100644 --- a/avm/res/analysis-services/server/main.json +++ b/avm/res/analysis-services/server/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "15159283808347195170" + "version": "0.26.54.24096", + "templateHash": "1590669612196455003" }, "name": "Analysis Services Servers", "description": "This module deploys an Analysis Services Server.", diff --git a/avm/res/analysis-services/server/tests/e2e/defaults/main.test.bicep b/avm/res/analysis-services/server/tests/e2e/defaults/main.test.bicep index 9eff12c840..22f5ddf455 100644 --- a/avm/res/analysis-services/server/tests/e2e/defaults/main.test.bicep +++ b/avm/res/analysis-services/server/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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}' - location: resourceLocation +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}' + location: resourceLocation + } } -}] +] diff --git a/avm/res/analysis-services/server/tests/e2e/max/main.test.bicep b/avm/res/analysis-services/server/tests/e2e/max/main.test.bicep index 9f52b51d27..36954fb7b2 100644 --- a/avm/res/analysis-services/server/tests/e2e/max/main.test.bicep +++ b/avm/res/analysis-services/server/tests/e2e/max/main.test.bicep @@ -59,75 +59,80 @@ 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}' - location: resourceLocation - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - skuName: 'S0' - skuCapacity: 1 - firewallSettings: { - firewallRules: [ - { - firewallRuleName: 'AllowFromAll' - rangeStart: '0.0.0.0' - rangeEnd: '255.255.255.255' - } - ] - enablePowerBIService: true - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}' + location: resourceLocation + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - 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: [ + skuName: 'S0' + skuCapacity: 1 + firewallSettings: { + firewallRules: [ { - category: 'AllMetrics' + firewallRuleName: 'AllowFromAll' + rangeStart: '0.0.0.0' + rangeEnd: '255.255.255.255' } ] - logCategoriesAndGroups: [ - { - category: 'Engine' - } - { - category: 'Service' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + enablePowerBIService: true + } + 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' + } + ] + logCategoriesAndGroups: [ + { + category: 'Engine' + } + { + category: 'Service' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/analysis-services/server/tests/e2e/waf-aligned/main.test.bicep b/avm/res/analysis-services/server/tests/e2e/waf-aligned/main.test.bicep index 862f260663..aeab0feba2 100644 --- a/avm/res/analysis-services/server/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/analysis-services/server/tests/e2e/waf-aligned/main.test.bicep @@ -50,57 +50,59 @@ 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}' - location: resourceLocation - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - skuName: 'S0' - skuCapacity: 1 - firewallSettings: { - firewallRules: [ - { - firewallRuleName: 'AllowFromAll' - rangeStart: '0.0.0.0' - rangeEnd: '255.255.255.255' - } - ] - enablePowerBIService: true - } - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - logCategoriesAndGroups: [ - { - category: 'Engine' - } +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}' + location: resourceLocation + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + skuName: 'S0' + skuCapacity: 1 + firewallSettings: { + firewallRules: [ { - category: 'Service' + firewallRuleName: 'AllowFromAll' + rangeStart: '0.0.0.0' + rangeEnd: '255.255.255.255' } ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + enablePowerBIService: true + } + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + logCategoriesAndGroups: [ + { + category: 'Engine' + } + { + category: 'Service' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + diagnosticDependencies + ] } - dependsOn: [ - diagnosticDependencies - ] -}] +] 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 bd4daa7b03..b20b0388c7 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.25.53.49325", - "templateHash": "4002198465184356188" + "version": "0.26.54.24096", + "templateHash": "14411287735172753559" }, "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/main.json b/avm/res/api-management/service/api/main.json index 09a9425d19..149062f9e8 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.25.53.49325", - "templateHash": "857470281336543408" + "version": "0.26.54.24096", + "templateHash": "5827467280453778347" }, "name": "API Management Service APIs", "description": "This module deploys an API Management Service API.", @@ -267,8 +267,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "5383521143080449228" + "version": "0.26.54.24096", + "templateHash": "11734266416309377949" }, "name": "API Management Service APIs Policies", "description": "This module deploys an API Management Service API Policy.", diff --git a/avm/res/api-management/service/api/policy/main.json b/avm/res/api-management/service/api/policy/main.json index 4667963a3b..bcbaf1d3bc 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.25.53.49325", - "templateHash": "5383521143080449228" + "version": "0.26.54.24096", + "templateHash": "11734266416309377949" }, "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 10e75c27e4..78869fc966 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.25.53.49325", - "templateHash": "6703063831636643162" + "version": "0.26.54.24096", + "templateHash": "505882801529152233" }, "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 2e1bca38c9..bba5ebcc1f 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.25.53.49325", - "templateHash": "16587888030936573636" + "version": "0.26.54.24096", + "templateHash": "5914852504306173482" }, "name": "API Management Service Backends", "description": "This module deploys an API Management Service Backend.", diff --git a/avm/res/api-management/service/cache/main.json b/avm/res/api-management/service/cache/main.json index 38eb6d1873..537d4e1259 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.25.53.49325", - "templateHash": "1295772952565058470" + "version": "0.26.54.24096", + "templateHash": "5452536693649070190" }, "name": "API Management Service Caches", "description": "This module deploys an API Management Service Cache.", diff --git a/avm/res/api-management/service/identity-provider/main.json b/avm/res/api-management/service/identity-provider/main.json index 6d182b6014..d1ac06182d 100644 --- a/avm/res/api-management/service/identity-provider/main.json +++ b/avm/res/api-management/service/identity-provider/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17146377320278316178" + "version": "0.26.54.24096", + "templateHash": "6944159515007886666" }, "name": "API Management Service Identity Providers", "description": "This module deploys an API Management Service Identity Provider.", diff --git a/avm/res/api-management/service/named-value/main.json b/avm/res/api-management/service/named-value/main.json index 860c79be1c..2087682ca4 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.25.53.49325", - "templateHash": "5043439748386656207" + "version": "0.26.54.24096", + "templateHash": "17256518550792037410" }, "name": "API Management Service Named Values", "description": "This module deploys an API Management Service Named Value.", diff --git a/avm/res/api-management/service/policy/main.json b/avm/res/api-management/service/policy/main.json index bb46dd0c56..a2d8a0624c 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.25.53.49325", - "templateHash": "3643398305472631880" + "version": "0.26.54.24096", + "templateHash": "12407621079025229005" }, "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 0e3c01eaf1..510cbe1b2c 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.25.53.49325", - "templateHash": "14726250901514511689" + "version": "0.26.54.24096", + "templateHash": "6528716876560144579" }, "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 fce4061640..6e0c22412b 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.25.53.49325", - "templateHash": "2508310027677163402" + "version": "0.26.54.24096", + "templateHash": "2440306385645798125" }, "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 2091c80834..af4900659f 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.25.53.49325", - "templateHash": "14996351450231036018" + "version": "0.26.54.24096", + "templateHash": "7056381119937736015" }, "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 d1bbdbe274..36c877e581 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.25.53.49325", - "templateHash": "10657321045680066427" + "version": "0.26.54.24096", + "templateHash": "2407987626180908324" }, "name": "API Management Service Products", "description": "This module deploys an API Management Service Product.", @@ -126,8 +126,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2508310027677163402" + "version": "0.26.54.24096", + "templateHash": "2440306385645798125" }, "name": "API Management Service Products APIs", "description": "This module deploys an API Management Service Product API.", @@ -216,8 +216,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14996351450231036018" + "version": "0.26.54.24096", + "templateHash": "7056381119937736015" }, "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 70e72bc609..7bfb9de555 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.25.53.49325", - "templateHash": "16952030877948084799" + "version": "0.26.54.24096", + "templateHash": "12071485798846786639" }, "name": "API Management Service Subscriptions", "description": "This module deploys an API Management Service Subscription.", 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 0a888d3aaa..cc5f75de77 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.25.53.49325", - "templateHash": "16990071481669469313" + "version": "0.26.54.24096", + "templateHash": "8492150446155311380" }, "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 d80856f18e..124481d13b 100644 --- a/avm/res/app-configuration/configuration-store/main.bicep +++ b/avm/res/app-configuration/configuration-store/main.bicep @@ -67,56 +67,92 @@ param enableTelemetry bool = true @description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') param privateEndpoints privateEndpointType -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 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 builtInRoleNames = { - 'App Compliance Automation Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f37683f-2463-46b6-9ce7-9b788b988ba2') - 'App Compliance Automation Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ffc6bbe0-e443-4c3b-bf54-26581bb2f78e') - 'App Configuration Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b') - 'App Configuration Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '516239f1-63e1-4d78-a4de-a74fb236a071') + 'App Compliance Automation Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '0f37683f-2463-46b6-9ce7-9b788b988ba2' + ) + 'App Compliance Automation Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'ffc6bbe0-e443-4c3b-bf54-26581bb2f78e' + ) + 'App Configuration Data Owner': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b' + ) + 'App Configuration Data Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '516239f1-63e1-4d78-a4de-a74fb236a071' + ) 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.appconfiguration-configurationstore.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.appconfiguration-configurationstore.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} - -resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId)) { - name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) - scope: resourceGroup(split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4]) - resource cMKKey 'keys@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { - name: customerManagedKey.?keyName ?? 'dummyKey' +resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = + if (!empty(customerManagedKey.?keyVaultResourceId)) { + name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) + scope: resourceGroup( + split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], + split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4] + ) + + resource cMKKey 'keys@2023-02-01' existing = + if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { + name: customerManagedKey.?keyName ?? 'dummyKey' + } } -} -resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { - name: last(split(customerManagedKey.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) - scope: resourceGroup(split((customerManagedKey.?userAssignedIdentityResourceId ?? '//'), '/')[2], split((customerManagedKey.?userAssignedIdentityResourceId ?? '////'), '/')[4]) -} +resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = + if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { + name: last(split(customerManagedKey.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) + scope: resourceGroup( + split((customerManagedKey.?userAssignedIdentityResourceId ?? '//'), '/')[2], + split((customerManagedKey.?userAssignedIdentityResourceId ?? '////'), '/')[4] + ) + } resource configurationStore 'Microsoft.AppConfiguration/configurationStores@2023-03-01' = { name: name @@ -130,116 +166,151 @@ resource configurationStore 'Microsoft.AppConfiguration/configurationStores@2023 createMode: createMode disableLocalAuth: disableLocalAuth enablePurgeProtection: sku == 'Free' ? false : enablePurgeProtection - encryption: !empty(customerManagedKey) ? { - keyVaultProperties: { - keyIdentifier: !empty(customerManagedKey.?keyVersion ?? '') ? '${cMKKeyVault::cMKKey.properties.keyUri}/${customerManagedKey!.keyVersion}' : cMKKeyVault::cMKKey.properties.keyUriWithVersion - identityClientId: !empty(customerManagedKey.?userAssignedIdentityResourceId ?? '') ? cMKUserAssignedIdentity.properties.clientId : null - } - } : null - publicNetworkAccess: !empty(publicNetworkAccess) ? any(publicNetworkAccess) : (!empty(privateEndpoints) ? 'Disabled' : 'Enabled') + encryption: !empty(customerManagedKey) + ? { + keyVaultProperties: { + keyIdentifier: !empty(customerManagedKey.?keyVersion ?? '') + ? '${cMKKeyVault::cMKKey.properties.keyUri}/${customerManagedKey!.keyVersion}' + : cMKKeyVault::cMKKey.properties.keyUriWithVersion + identityClientId: !empty(customerManagedKey.?userAssignedIdentityResourceId ?? '') + ? cMKUserAssignedIdentity.properties.clientId + : null + } + } + : null + publicNetworkAccess: !empty(publicNetworkAccess) + ? any(publicNetworkAccess) + : (!empty(privateEndpoints) ? 'Disabled' : 'Enabled') softDeleteRetentionInDays: sku == 'Free' ? 0 : softDeleteRetentionInDays } } -module configurationStore_keyValues 'key-value/main.bicep' = [for (keyValue, index) in (keyValues ?? []): { - name: '${uniqueString(deployment().name, location)}-AppConfig-KeyValues-${index}' - params: { - appConfigurationName: configurationStore.name - name: keyValue.name - value: keyValue.value - contentType: keyValue.?contentType - tags: keyValue.?tags ?? tags +module configurationStore_keyValues 'key-value/main.bicep' = [ + for (keyValue, index) in (keyValues ?? []): { + name: '${uniqueString(deployment().name, location)}-AppConfig-KeyValues-${index}' + params: { + appConfigurationName: configurationStore.name + name: keyValue.name + value: keyValue.value + contentType: keyValue.?contentType + tags: keyValue.?tags ?? tags + } } -}] +] -resource configurationStore_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.' +resource configurationStore_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: configurationStore } - scope: configurationStore -} -resource configurationStore_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource configurationStore_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: configurationStore } - scope: configurationStore -}] +] -resource configurationStore_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(configurationStore.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource configurationStore_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(configurationStore.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: configurationStore } - scope: configurationStore -}] +] @batchSize(1) -module configurationStore_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.1' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-configurationStore-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(configurationStore.id, '/'))}-${privateEndpoint.?service ?? 'configurationStores'}-${index}' - privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(configurationStore.id, '/'))}-${privateEndpoint.?service ?? 'configurationStores'}-${index}' - properties: { - privateLinkServiceId: configurationStore.id - groupIds: [ - privateEndpoint.?service ?? 'configurationStores' +module configurationStore_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.1' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-configurationStore-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(configurationStore.id, '/'))}-${privateEndpoint.?service ?? 'configurationStores'}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(configurationStore.id, '/'))}-${privateEndpoint.?service ?? 'configurationStores'}-${index}' + properties: { + privateLinkServiceId: configurationStore.id + groupIds: [ + privateEndpoint.?service ?? 'configurationStores' + ] + } + } ] - } - } - ] : null - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(configurationStore.id, '/'))}-${privateEndpoint.?service ?? 'configurationStores'}-${index}' - properties: { - privateLinkServiceId: configurationStore.id - groupIds: [ - privateEndpoint.?service ?? 'configurationStores' + : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(configurationStore.id, '/'))}-${privateEndpoint.?service ?? 'configurationStores'}-${index}' + properties: { + privateLinkServiceId: configurationStore.id + groupIds: [ + privateEndpoint.?service ?? 'configurationStores' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] +] @description('The name of the app configuration.') output name string = configurationStore.name diff --git a/avm/res/app-configuration/configuration-store/main.json b/avm/res/app-configuration/configuration-store/main.json index 558a7bfb28..9f862cd382 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.25.53.49325", - "templateHash": "2210459796702021612" + "version": "0.26.54.24096", + "templateHash": "17308644596595948852" }, "name": "App Configuration Stores", "description": "This module deploys an App Configuration Store.", @@ -779,8 +779,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16990071481669469313" + "version": "0.26.54.24096", + "templateHash": "8492150446155311380" }, "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/tests/e2e/defaults/main.test.bicep b/avm/res/app-configuration/configuration-store/tests/e2e/defaults/main.test.bicep index 89c9a732fb..990968dd9a 100644 --- a/avm/res/app-configuration/configuration-store/tests/e2e/defaults/main.test.bicep +++ b/avm/res/app-configuration/configuration-store/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2023-07-01' = { // ============== // @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 +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 + } } -}] +] diff --git a/avm/res/app-configuration/configuration-store/tests/e2e/encr/dependencies.bicep b/avm/res/app-configuration/configuration-store/tests/e2e/encr/dependencies.bicep index bebad9a289..bd17946f56 100644 --- a/avm/res/app-configuration/configuration-store/tests/e2e/encr/dependencies.bicep +++ b/avm/res/app-configuration/configuration-store/tests/e2e/encr/dependencies.bicep @@ -43,7 +43,10 @@ resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { scope: keyVault::key properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '12338af0-0e69-4776-bea7-57ae8d297424' + ) // Key Vault Crypto User principalType: 'ServicePrincipal' } } diff --git a/avm/res/app-configuration/configuration-store/tests/e2e/encr/main.test.bicep b/avm/res/app-configuration/configuration-store/tests/e2e/encr/main.test.bicep index ad837aa7c2..6c8874859b 100644 --- a/avm/res/app-configuration/configuration-store/tests/e2e/encr/main.test.bicep +++ b/avm/res/app-configuration/configuration-store/tests/e2e/encr/main.test.bicep @@ -50,40 +50,42 @@ 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 - createMode: 'Default' - disableLocalAuth: false - enablePurgeProtection: false - keyValues: [ - { - contentType: 'contentType' - name: 'keyName' - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId +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 + createMode: 'Default' + disableLocalAuth: false + enablePurgeProtection: false + keyValues: [ + { + contentType: 'contentType' + name: 'keyName' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } + principalType: 'ServicePrincipal' + } + ] + value: 'valueName' + } + ] + softDeleteRetentionInDays: 1 + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId ] - value: 'valueName' } - ] - softDeleteRetentionInDays: 1 - managedIdentities: { - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - customerManagedKey: { - keyName: nestedDependencies.outputs.keyName - keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - userAssignedIdentityResourceId: nestedDependencies.outputs.managedIdentityResourceId + customerManagedKey: { + keyName: nestedDependencies.outputs.keyName + keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + userAssignedIdentityResourceId: nestedDependencies.outputs.managedIdentityResourceId + } } } -}] +] diff --git a/avm/res/app-configuration/configuration-store/tests/e2e/max/main.test.bicep b/avm/res/app-configuration/configuration-store/tests/e2e/max/main.test.bicep index a58054c1ea..5028ef0929 100644 --- a/avm/res/app-configuration/configuration-store/tests/e2e/max/main.test.bicep +++ b/avm/res/app-configuration/configuration-store/tests/e2e/max/main.test.bicep @@ -59,79 +59,84 @@ 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 - createMode: 'Default' - 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 + createMode: 'Default' + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + disableLocalAuth: false + enablePurgeProtection: false + keyValues: [ + { + contentType: 'contentType' + name: 'keyName' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + value: 'valueName' + } + { + name: 'keyName2' + value: 'valueName2' + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - disableLocalAuth: false - enablePurgeProtection: false - keyValues: [ - { - contentType: 'contentType' - name: 'keyName' - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } + 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' + } + ] + softDeleteRetentionInDays: 1 + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId ] - value: 'valueName' } - { - name: 'keyName2' - value: 'valueName2' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - 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' - } - ] - softDeleteRetentionInDays: 1 - managedIdentities: { - systemAssigned: true - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/app-configuration/configuration-store/tests/e2e/pe/main.test.bicep b/avm/res/app-configuration/configuration-store/tests/e2e/pe/main.test.bicep index 26e34c15cb..569c308146 100644 --- a/avm/res/app-configuration/configuration-store/tests/e2e/pe/main.test.bicep +++ b/avm/res/app-configuration/configuration-store/tests/e2e/pe/main.test.bicep @@ -45,34 +45,36 @@ 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 - createMode: 'Default' - disableLocalAuth: false - enablePurgeProtection: false - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +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 + createMode: 'Default' + disableLocalAuth: false + enablePurgeProtection: false + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] } - } - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - } - ] - softDeleteRetentionInDays: 1 + ] + softDeleteRetentionInDays: 1 + } } -}] +] diff --git a/avm/res/app-configuration/configuration-store/tests/e2e/waf-aligned/main.test.bicep b/avm/res/app-configuration/configuration-store/tests/e2e/waf-aligned/main.test.bicep index cdd7faa503..6d3b70e64c 100644 --- a/avm/res/app-configuration/configuration-store/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/app-configuration/configuration-store/tests/e2e/waf-aligned/main.test.bicep @@ -50,35 +50,37 @@ 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 - createMode: 'Default' - diagnosticSettings: [ - { - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - disableLocalAuth: false - enablePurgeProtection: false - keyValues: [ - { - contentType: 'contentType' - name: 'keyName' - value: 'valueName' +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 + createMode: 'Default' + diagnosticSettings: [ + { + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + disableLocalAuth: false + enablePurgeProtection: false + keyValues: [ + { + contentType: 'contentType' + name: 'keyName' + value: 'valueName' + } + ] + softDeleteRetentionInDays: 1 + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - softDeleteRetentionInDays: 1 - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/automation/automation-account/job-schedule/main.json b/avm/res/automation/automation-account/job-schedule/main.json index 170fa3ee8a..1d7dbb1dfe 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.25.53.49325", - "templateHash": "4183701486282199551" + "version": "0.26.54.24096", + "templateHash": "3709450248827326388" }, "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 9db1af88c2..bbd2b9700e 100644 --- a/avm/res/automation/automation-account/main.bicep +++ b/avm/res/automation/automation-account/main.bicep @@ -74,56 +74,92 @@ param tags object? @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -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 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 builtInRoleNames = { - 'Automation Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f353d9bd-d4a6-484e-a77a-8050b599b867') - 'Automation Job Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4fe576fe-1146-4730-92eb-48519fa6bf9f') - 'Automation Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd3881f73-407a-4167-8283-e981cbba0404') - 'Automation Runbook Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5fb5aef8-1081-4b8e-bb16-9d5d0385bab5') + 'Automation Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f353d9bd-d4a6-484e-a77a-8050b599b867' + ) + 'Automation Job Operator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '4fe576fe-1146-4730-92eb-48519fa6bf9f' + ) + 'Automation Operator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'd3881f73-407a-4167-8283-e981cbba0404' + ) + 'Automation Runbook Operator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '5fb5aef8-1081-4b8e-bb16-9d5d0385bab5' + ) 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.automation-automationaccount.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.automation-automationaccount.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} - -resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId)) { - name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) - scope: resourceGroup(split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4]) - resource cMKKey 'keys@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { - name: customerManagedKey.?keyName ?? 'dummyKey' +resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = + if (!empty(customerManagedKey.?keyVaultResourceId)) { + name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) + scope: resourceGroup( + split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], + split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4] + ) + + resource cMKKey 'keys@2023-02-01' existing = + if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { + name: customerManagedKey.?keyName ?? 'dummyKey' + } } -} -resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { - name: last(split(customerManagedKey.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) - scope: resourceGroup(split((customerManagedKey.?userAssignedIdentityResourceId ?? '//'), '/')[2], split((customerManagedKey.?userAssignedIdentityResourceId ?? '////'), '/')[4]) -} +resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = + if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { + name: last(split(customerManagedKey.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) + scope: resourceGroup( + split((customerManagedKey.?userAssignedIdentityResourceId ?? '//'), '/')[2], + split((customerManagedKey.?userAssignedIdentityResourceId ?? '////'), '/')[4] + ) + } resource automationAccount 'Microsoft.Automation/automationAccounts@2022-08-08' = { name: name @@ -134,255 +170,353 @@ resource automationAccount 'Microsoft.Automation/automationAccounts@2022-08-08' sku: { name: skuName } - encryption: !empty(customerManagedKey) ? { - keySource: 'Microsoft.KeyVault' - identity: !empty(customerManagedKey.?userAssignedIdentityResourceId) ? { - userAssignedIdentity: cMKUserAssignedIdentity.id - } : null - keyVaultProperties: { - keyName: customerManagedKey!.keyName - keyVaultUri: cMKKeyVault.properties.vaultUri - keyVersion: !empty(customerManagedKey.?keyVersion ?? '') ? customerManagedKey!.keyVersion : last(split(cMKKeyVault::cMKKey.properties.keyUriWithVersion, '/')) - } - } : null - publicNetworkAccess: !empty(publicNetworkAccess) ? (publicNetworkAccess == 'Disabled' ? false : true) : (!empty(privateEndpoints) ? false : null) + encryption: !empty(customerManagedKey) + ? { + keySource: 'Microsoft.KeyVault' + identity: !empty(customerManagedKey.?userAssignedIdentityResourceId) + ? { + userAssignedIdentity: cMKUserAssignedIdentity.id + } + : null + keyVaultProperties: { + keyName: customerManagedKey!.keyName + keyVaultUri: cMKKeyVault.properties.vaultUri + keyVersion: !empty(customerManagedKey.?keyVersion ?? '') + ? customerManagedKey!.keyVersion + : last(split(cMKKeyVault::cMKKey.properties.keyUriWithVersion, '/')) + } + } + : null + publicNetworkAccess: !empty(publicNetworkAccess) + ? (publicNetworkAccess == 'Disabled' ? false : true) + : (!empty(privateEndpoints) ? false : null) disableLocalAuth: disableLocalAuth } } -module automationAccount_modules 'module/main.bicep' = [for (module, index) in modules: { - name: '${uniqueString(deployment().name, location)}-AutoAccount-Module-${index}' - params: { - name: module.name - automationAccountName: automationAccount.name - version: module.version - uri: module.uri - location: location - tags: module.?tags ?? tags +module automationAccount_modules 'module/main.bicep' = [ + for (module, index) in modules: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-Module-${index}' + params: { + name: module.name + automationAccountName: automationAccount.name + version: module.version + uri: module.uri + location: location + tags: module.?tags ?? tags + } } -}] - -module automationAccount_schedules 'schedule/main.bicep' = [for (schedule, index) in schedules: { - name: '${uniqueString(deployment().name, location)}-AutoAccount-Schedule-${index}' - params: { - name: schedule.name - automationAccountName: automationAccount.name - advancedSchedule: contains(schedule, 'advancedSchedule') ? schedule.advancedSchedule : null - 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 : '' +] + +module automationAccount_schedules 'schedule/main.bicep' = [ + for (schedule, index) in schedules: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-Schedule-${index}' + params: { + name: schedule.name + automationAccountName: automationAccount.name + advancedSchedule: contains(schedule, 'advancedSchedule') ? schedule.advancedSchedule : null + 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 : '' + } } -}] - -module automationAccount_runbooks 'runbook/main.bicep' = [for (runbook, index) in runbooks: { - name: '${uniqueString(deployment().name, location)}-AutoAccount-Runbook-${index}' - params: { - 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 : '' - sasTokenValidityLength: runbook.?sasTokenValidityLength - scriptStorageAccountResourceId: runbook.?scriptStorageAccountResourceId - location: location - tags: runbook.?tags ?? tags +] + +module automationAccount_runbooks 'runbook/main.bicep' = [ + for (runbook, index) in runbooks: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-Runbook-${index}' + params: { + 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 : '' + sasTokenValidityLength: runbook.?sasTokenValidityLength + scriptStorageAccountResourceId: runbook.?scriptStorageAccountResourceId + location: location + tags: runbook.?tags ?? tags + } } -}] - -module automationAccount_jobSchedules 'job-schedule/main.bicep' = [for (jobSchedule, index) in jobSchedules: { - name: '${uniqueString(deployment().name, location)}-AutoAccount-JobSchedule-${index}' - params: { - automationAccountName: automationAccount.name - runbookName: jobSchedule.runbookName - scheduleName: jobSchedule.scheduleName - parameters: contains(jobSchedule, 'parameters') ? jobSchedule.parameters : {} - runOn: contains(jobSchedule, 'runOn') ? jobSchedule.runOn : '' +] + +module automationAccount_jobSchedules 'job-schedule/main.bicep' = [ + for (jobSchedule, index) in jobSchedules: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-JobSchedule-${index}' + params: { + automationAccountName: automationAccount.name + runbookName: jobSchedule.runbookName + scheduleName: jobSchedule.scheduleName + parameters: contains(jobSchedule, 'parameters') ? jobSchedule.parameters : {} + runOn: contains(jobSchedule, 'runOn') ? jobSchedule.runOn : '' + } + dependsOn: [ + automationAccount_schedules + automationAccount_runbooks + ] } - dependsOn: [ - automationAccount_schedules - automationAccount_runbooks - ] -}] - -module automationAccount_variables 'variable/main.bicep' = [for (variable, index) in variables: { - name: '${uniqueString(deployment().name, location)}-AutoAccount-Variable-${index}' - params: { - automationAccountName: automationAccount.name - name: variable.name - description: contains(variable, 'description') ? variable.description : '' - value: variable.value - isEncrypted: contains(variable, 'isEncrypted') ? variable.isEncrypted : true +] + +module automationAccount_variables 'variable/main.bicep' = [ + for (variable, index) in variables: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-Variable-${index}' + params: { + automationAccountName: automationAccount.name + name: variable.name + description: contains(variable, 'description') ? variable.description : '' + value: variable.value + isEncrypted: contains(variable, 'isEncrypted') ? variable.isEncrypted : true + } } -}] - -module automationAccount_linkedService '../../operational-insights/workspace/linked-service/main.bicep' = if (!empty(linkedWorkspaceResourceId)) { - name: '${uniqueString(deployment().name, location)}-AutoAccount-LinkedService' - params: { - name: 'automation' - logAnalyticsWorkspaceName: last(split(linkedWorkspaceResourceId, '/'))! - resourceId: automationAccount.id - tags: tags +] + +module automationAccount_linkedService '../../operational-insights/workspace/linked-service/main.bicep' = + if (!empty(linkedWorkspaceResourceId)) { + name: '${uniqueString(deployment().name, location)}-AutoAccount-LinkedService' + params: { + name: 'automation' + logAnalyticsWorkspaceName: last(split(linkedWorkspaceResourceId, '/'))! + resourceId: automationAccount.id + tags: tags + } + // This is to support linked services to law in different subscription and resource group than the automation account. + // The current scope is used by default if no linked service is intended to be created. + scope: resourceGroup( + (!empty(linkedWorkspaceResourceId) + ? (split((!empty(linkedWorkspaceResourceId) ? linkedWorkspaceResourceId : '//'), '/')[2]) + : subscription().subscriptionId), + !empty(linkedWorkspaceResourceId) + ? (split((!empty(linkedWorkspaceResourceId) ? linkedWorkspaceResourceId : '////'), '/')[4]) + : resourceGroup().name + ) } - // This is to support linked services to law in different subscription and resource group than the automation account. - // The current scope is used by default if no linked service is intended to be created. - scope: resourceGroup((!empty(linkedWorkspaceResourceId) ? (split((!empty(linkedWorkspaceResourceId) ? linkedWorkspaceResourceId : '//'), '/')[2]) : subscription().subscriptionId), !empty(linkedWorkspaceResourceId) ? (split((!empty(linkedWorkspaceResourceId) ? linkedWorkspaceResourceId : '////'), '/')[4]) : resourceGroup().name) -} -module automationAccount_solutions 'br/public:avm/res/operations-management/solution:0.1.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' - enableTelemetry: enableTelemetry - } - // This is to support solution to law in different subscription and resource group than the automation account. - // The current scope is used by default if no linked service is intended to be created. - scope: resourceGroup((!empty(linkedWorkspaceResourceId) ? (split((!empty(linkedWorkspaceResourceId) ? linkedWorkspaceResourceId : '//'), '/')[2]) : subscription().subscriptionId), !empty(linkedWorkspaceResourceId) ? (split((!empty(linkedWorkspaceResourceId) ? linkedWorkspaceResourceId : '////'), '/')[4]) : resourceGroup().name) - dependsOn: [ - automationAccount_linkedService - ] -}] - -module automationAccount_softwareUpdateConfigurations 'software-update-configuration/main.bicep' = [for (softwareUpdateConfiguration, index) in softwareUpdateConfigurations: { - name: '${uniqueString(deployment().name, location)}-AutoAccount-SwUpdateConfig-${index}' - params: { - name: softwareUpdateConfiguration.name - automationAccountName: automationAccount.name - frequency: softwareUpdateConfiguration.frequency - operatingSystem: softwareUpdateConfiguration.operatingSystem - rebootSetting: softwareUpdateConfiguration.rebootSetting - azureVirtualMachines: contains(softwareUpdateConfiguration, 'azureVirtualMachines') ? softwareUpdateConfiguration.azureVirtualMachines : [] - excludeUpdates: contains(softwareUpdateConfiguration, 'excludeUpdates') ? softwareUpdateConfiguration.excludeUpdates : [] - expiryTime: contains(softwareUpdateConfiguration, 'expiryTime') ? softwareUpdateConfiguration.expiryTime : '' - expiryTimeOffsetMinutes: contains(softwareUpdateConfiguration, 'expiryTimeOffsetMinutes') ? softwareUpdateConfiguration.expiryTimeOffsetMinute : 0 - includeUpdates: contains(softwareUpdateConfiguration, 'includeUpdates') ? softwareUpdateConfiguration.includeUpdates : [] - interval: contains(softwareUpdateConfiguration, 'interval') ? softwareUpdateConfiguration.interval : 1 - isEnabled: contains(softwareUpdateConfiguration, 'isEnabled') ? softwareUpdateConfiguration.isEnabled : true - maintenanceWindow: contains(softwareUpdateConfiguration, 'maintenanceWindow') ? softwareUpdateConfiguration.maintenanceWindow : 'PT2H' - monthDays: contains(softwareUpdateConfiguration, 'monthDays') ? softwareUpdateConfiguration.monthDays : [] - monthlyOccurrences: contains(softwareUpdateConfiguration, 'monthlyOccurrences') ? softwareUpdateConfiguration.monthlyOccurrences : [] - nextRun: contains(softwareUpdateConfiguration, 'nextRun') ? softwareUpdateConfiguration.nextRun : '' - nextRunOffsetMinutes: contains(softwareUpdateConfiguration, 'nextRunOffsetMinutes') ? softwareUpdateConfiguration.nextRunOffsetMinutes : 0 - nonAzureComputerNames: contains(softwareUpdateConfiguration, 'nonAzureComputerNames') ? softwareUpdateConfiguration.nonAzureComputerNames : [] - nonAzureQueries: contains(softwareUpdateConfiguration, 'nonAzureQueries') ? softwareUpdateConfiguration.nonAzureQueries : [] - postTaskParameters: contains(softwareUpdateConfiguration, 'postTaskParameters') ? softwareUpdateConfiguration.postTaskParameters : {} - postTaskSource: contains(softwareUpdateConfiguration, 'postTaskSource') ? softwareUpdateConfiguration.postTaskSource : '' - preTaskParameters: contains(softwareUpdateConfiguration, 'preTaskParameters') ? softwareUpdateConfiguration.preTaskParameters : {} - preTaskSource: contains(softwareUpdateConfiguration, 'preTaskSource') ? softwareUpdateConfiguration.preTaskSource : '' - scheduleDescription: contains(softwareUpdateConfiguration, 'scheduleDescription') ? softwareUpdateConfiguration.scheduleDescription : '' - scopeByLocations: contains(softwareUpdateConfiguration, 'scopeByLocations') ? softwareUpdateConfiguration.scopeByLocations : [] - scopeByResources: contains(softwareUpdateConfiguration, 'scopeByResources') ? softwareUpdateConfiguration.scopeByResources : [ - subscription().id +module automationAccount_solutions 'br/public:avm/res/operations-management/solution:0.1.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' + enableTelemetry: enableTelemetry + } + // This is to support solution to law in different subscription and resource group than the automation account. + // The current scope is used by default if no linked service is intended to be created. + scope: resourceGroup( + (!empty(linkedWorkspaceResourceId) + ? (split((!empty(linkedWorkspaceResourceId) ? linkedWorkspaceResourceId : '//'), '/')[2]) + : subscription().subscriptionId), + !empty(linkedWorkspaceResourceId) + ? (split((!empty(linkedWorkspaceResourceId) ? linkedWorkspaceResourceId : '////'), '/')[4]) + : resourceGroup().name + ) + dependsOn: [ + automationAccount_linkedService ] - 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' + } +] + +module automationAccount_softwareUpdateConfigurations 'software-update-configuration/main.bicep' = [ + for (softwareUpdateConfiguration, index) in softwareUpdateConfigurations: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-SwUpdateConfig-${index}' + params: { + name: softwareUpdateConfiguration.name + automationAccountName: automationAccount.name + frequency: softwareUpdateConfiguration.frequency + operatingSystem: softwareUpdateConfiguration.operatingSystem + rebootSetting: softwareUpdateConfiguration.rebootSetting + azureVirtualMachines: contains(softwareUpdateConfiguration, 'azureVirtualMachines') + ? softwareUpdateConfiguration.azureVirtualMachines + : [] + excludeUpdates: contains(softwareUpdateConfiguration, 'excludeUpdates') + ? softwareUpdateConfiguration.excludeUpdates + : [] + expiryTime: contains(softwareUpdateConfiguration, 'expiryTime') ? softwareUpdateConfiguration.expiryTime : '' + expiryTimeOffsetMinutes: contains(softwareUpdateConfiguration, 'expiryTimeOffsetMinutes') + ? softwareUpdateConfiguration.expiryTimeOffsetMinute + : 0 + includeUpdates: contains(softwareUpdateConfiguration, 'includeUpdates') + ? softwareUpdateConfiguration.includeUpdates + : [] + interval: contains(softwareUpdateConfiguration, 'interval') ? softwareUpdateConfiguration.interval : 1 + isEnabled: contains(softwareUpdateConfiguration, 'isEnabled') ? softwareUpdateConfiguration.isEnabled : true + maintenanceWindow: contains(softwareUpdateConfiguration, 'maintenanceWindow') + ? softwareUpdateConfiguration.maintenanceWindow + : 'PT2H' + monthDays: contains(softwareUpdateConfiguration, 'monthDays') ? softwareUpdateConfiguration.monthDays : [] + monthlyOccurrences: contains(softwareUpdateConfiguration, 'monthlyOccurrences') + ? softwareUpdateConfiguration.monthlyOccurrences + : [] + nextRun: contains(softwareUpdateConfiguration, 'nextRun') ? softwareUpdateConfiguration.nextRun : '' + nextRunOffsetMinutes: contains(softwareUpdateConfiguration, 'nextRunOffsetMinutes') + ? softwareUpdateConfiguration.nextRunOffsetMinutes + : 0 + nonAzureComputerNames: contains(softwareUpdateConfiguration, 'nonAzureComputerNames') + ? softwareUpdateConfiguration.nonAzureComputerNames + : [] + nonAzureQueries: contains(softwareUpdateConfiguration, 'nonAzureQueries') + ? softwareUpdateConfiguration.nonAzureQueries + : [] + postTaskParameters: contains(softwareUpdateConfiguration, 'postTaskParameters') + ? softwareUpdateConfiguration.postTaskParameters + : {} + postTaskSource: contains(softwareUpdateConfiguration, 'postTaskSource') + ? softwareUpdateConfiguration.postTaskSource + : '' + preTaskParameters: contains(softwareUpdateConfiguration, 'preTaskParameters') + ? softwareUpdateConfiguration.preTaskParameters + : {} + preTaskSource: contains(softwareUpdateConfiguration, 'preTaskSource') + ? softwareUpdateConfiguration.preTaskSource + : '' + scheduleDescription: contains(softwareUpdateConfiguration, 'scheduleDescription') + ? softwareUpdateConfiguration.scheduleDescription + : '' + scopeByLocations: contains(softwareUpdateConfiguration, 'scopeByLocations') + ? softwareUpdateConfiguration.scopeByLocations + : [] + scopeByResources: contains(softwareUpdateConfiguration, 'scopeByResources') + ? softwareUpdateConfiguration.scopeByResources + : [ + subscription().id + ] + scopeByTags: contains(softwareUpdateConfiguration, 'scopeByTags') ? softwareUpdateConfiguration.scopeByTags : {} + scopeByTagsOperation: contains(softwareUpdateConfiguration, 'scopeByTagsOperation') + ? softwareUpdateConfiguration.scopeByTagsOperation + : 'All' + startTime: contains(softwareUpdateConfiguration, 'startTime') ? softwareUpdateConfiguration.startTime : '' + timeZone: contains(softwareUpdateConfiguration, 'timeZone') ? softwareUpdateConfiguration.timeZone : 'UTC' + updateClassifications: contains(softwareUpdateConfiguration, 'updateClassifications') + ? softwareUpdateConfiguration.updateClassifications + : [ + 'Critical' + 'Security' + ] + weekDays: contains(softwareUpdateConfiguration, 'weekDays') ? softwareUpdateConfiguration.weekDays : [] + } + dependsOn: [ + automationAccount_solutions ] - weekDays: contains(softwareUpdateConfiguration, 'weekDays') ? softwareUpdateConfiguration.weekDays : [] } - dependsOn: [ - automationAccount_solutions - ] -}] +] -resource automationAccount_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.' +resource automationAccount_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: automationAccount } - scope: automationAccount -} -resource automationAccount_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource automationAccount_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: automationAccount } - scope: automationAccount -}] - -module automationAccount_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-automationAccount-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(automationAccount.id, '/'))}-${privateEndpoint.service}-${index}' - privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(automationAccount.id, '/'))}-${privateEndpoint.service}-${index}' - properties: { - privateLinkServiceId: automationAccount.id - groupIds: [ - privateEndpoint.service +] + +module automationAccount_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-automationAccount-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(automationAccount.id, '/'))}-${privateEndpoint.service}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(automationAccount.id, '/'))}-${privateEndpoint.service}-${index}' + properties: { + privateLinkServiceId: automationAccount.id + groupIds: [ + privateEndpoint.service + ] + } + } ] - } - } - ] : null - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(automationAccount.id, '/'))}-${privateEndpoint.service}-${index}' - properties: { - privateLinkServiceId: automationAccount.id - groupIds: [ - privateEndpoint.service + : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(automationAccount.id, '/'))}-${privateEndpoint.service}-${index}' + properties: { + privateLinkServiceId: automationAccount.id + groupIds: [ + privateEndpoint.service + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] +] -resource automationAccount_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(automationAccount.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource automationAccount_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(automationAccount.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: automationAccount } - scope: automationAccount -}] +] @description('The name of the deployed automation account.') output name string = automationAccount.name diff --git a/avm/res/automation/automation-account/main.json b/avm/res/automation/automation-account/main.json index c53dc5fcde..0b24e4fed3 100644 --- a/avm/res/automation/automation-account/main.json +++ b/avm/res/automation/automation-account/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "13780169676814518535" + "version": "0.26.54.24096", + "templateHash": "6662719167579233396" }, "name": "Automation Accounts", "description": "This module deploys an Azure Automation Account.", @@ -816,8 +816,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4277151232699761913" + "version": "0.26.54.24096", + "templateHash": "8037849223912660600" }, "name": "Automation Account Modules", "description": "This module deploys an Azure Automation Account Module.", @@ -958,8 +958,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3130545991088336783" + "version": "0.26.54.24096", + "templateHash": "10057879847143996563" }, "name": "Automation Account Schedules", "description": "This module deploys an Azure Automation Account Schedule.", @@ -1137,8 +1137,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16141039584915226874" + "version": "0.26.54.24096", + "templateHash": "14714097202201612277" }, "name": "Automation Account Runbooks", "description": "This module deploys an Azure Automation Account Runbook.", @@ -1337,8 +1337,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4183701486282199551" + "version": "0.26.54.24096", + "templateHash": "3709450248827326388" }, "name": "Automation Account Job Schedules", "description": "This module deploys an Azure Automation Account Job Schedule.", @@ -1465,8 +1465,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "15605588341437540157" + "version": "0.26.54.24096", + "templateHash": "1065450815403209329" }, "name": "Automation Account Variables", "description": "This module deploys an Azure Automation Account Variable.", @@ -1580,8 +1580,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14301767156435143002" + "version": "0.26.54.24096", + "templateHash": "7204307644126778192" }, "name": "Log Analytics Workspace Linked Services", "description": "This module deploys a Log Analytics Workspace Linked Service.", @@ -1899,8 +1899,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "6467431009828483672" + "version": "0.26.54.24096", + "templateHash": "7586828544795723203" }, "name": "Automation Account Software Update Configurations", "description": "This module deploys an Azure Automation Account Software Update Configuration.", diff --git a/avm/res/automation/automation-account/module/main.json b/avm/res/automation/automation-account/module/main.json index c151060111..546c8505d5 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.25.53.49325", - "templateHash": "4277151232699761913" + "version": "0.26.54.24096", + "templateHash": "8037849223912660600" }, "name": "Automation Account Modules", "description": "This module deploys an Azure Automation Account Module.", diff --git a/avm/res/automation/automation-account/runbook/main.bicep b/avm/res/automation/automation-account/runbook/main.bicep index ec1cd1ab8e..4f41bf68ca 100644 --- a/avm/res/automation/automation-account/runbook/main.bicep +++ b/avm/res/automation/automation-account/runbook/main.bicep @@ -50,20 +50,29 @@ var accountSasProperties = { signedProtocol: 'https' } - resource automationAccount 'Microsoft.Automation/automationAccounts@2022-08-08' existing = { name: automationAccountName } -resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' existing = if (!empty(scriptStorageAccountResourceId)) { - name: last(split((scriptStorageAccountResourceId ?? 'dummyVault'), '/')) - scope: resourceGroup(split((scriptStorageAccountResourceId ?? '//'), '/')[2], split((scriptStorageAccountResourceId ?? '////'), '/')[4]) -} +resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' existing = + if (!empty(scriptStorageAccountResourceId)) { + name: last(split((scriptStorageAccountResourceId ?? 'dummyVault'), '/')) + scope: resourceGroup( + split((scriptStorageAccountResourceId ?? '//'), '/')[2], + split((scriptStorageAccountResourceId ?? '////'), '/')[4] + ) + } -var publishContentLink = empty(uri) ? null : { - uri: !empty(uri) ? (empty(scriptStorageAccountResourceId) ? uri : '${uri}?${storageAccount.listAccountSas('2021-04-01', accountSasProperties).accountSasToken}') : null - version: !empty(version) ? version : null -} +var publishContentLink = empty(uri) + ? null + : { + uri: !empty(uri) + ? (empty(scriptStorageAccountResourceId) + ? uri + : '${uri}?${storageAccount.listAccountSas('2021-04-01', accountSasProperties).accountSasToken}') + : null + version: !empty(version) ? version : null + } resource runbook 'Microsoft.Automation/automationAccounts/runbooks@2022-08-08' = { name: name diff --git a/avm/res/automation/automation-account/runbook/main.json b/avm/res/automation/automation-account/runbook/main.json index 0761a0bce4..4f23a696b6 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.25.53.49325", - "templateHash": "16141039584915226874" + "version": "0.26.54.24096", + "templateHash": "14714097202201612277" }, "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 65e59ddfd4..4a8ef6d870 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.25.53.49325", - "templateHash": "3130545991088336783" + "version": "0.26.54.24096", + "templateHash": "10057879847143996563" }, "name": "Automation Account Schedules", "description": "This module deploys an Azure Automation Account Schedule.", 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 6354fa6b3e..2408a52a41 100644 --- a/avm/res/automation/automation-account/software-update-configuration/main.bicep +++ b/avm/res/automation/automation-account/software-update-configuration/main.bicep @@ -181,7 +181,11 @@ param scheduleDescription string = '' @description('Generated. Do not touch. Is used to provide the base time for time comparison for startTime. If startTime is specified in HH:MM format, baseTime is used to check if the provided startTime has passed, adding one day before setting the deployment schedule.') param baseTime string = utcNow('u') -var updateClassificationsVar = replace(replace(replace(replace(string(updateClassifications), ',', ', '), '[', ''), ']', ''), '"', '') +var updateClassificationsVar = replace( + replace(replace(replace(string(updateClassifications), ',', ', '), '[', ''), ']', ''), + '"', + '' +) resource automationAccount 'Microsoft.Automation/automationAccounts@2022-08-08' existing = { name: automationAccountName @@ -194,18 +198,22 @@ resource softwareUpdateConfiguration 'Microsoft.Automation/automationAccounts/so updateConfiguration: { operatingSystem: operatingSystem duration: maintenanceWindow - linux: ((operatingSystem == 'Linux') ? { - excludedPackageNameMasks: excludeUpdates - includedPackageNameMasks: includeUpdates - includedPackageClassifications: updateClassificationsVar - rebootSetting: rebootSetting - } : null) - windows: ((operatingSystem == 'Windows') ? { - excludedKbNumbers: excludeUpdates - includedKbNumbers: includeUpdates - includedUpdateClassifications: updateClassificationsVar - rebootSetting: rebootSetting - } : null) + linux: ((operatingSystem == 'Linux') + ? { + excludedPackageNameMasks: excludeUpdates + includedPackageNameMasks: includeUpdates + includedPackageClassifications: updateClassificationsVar + rebootSetting: rebootSetting + } + : null) + windows: ((operatingSystem == 'Windows') + ? { + excludedKbNumbers: excludeUpdates + includedKbNumbers: includeUpdates + includedUpdateClassifications: updateClassificationsVar + rebootSetting: rebootSetting + } + : null) targets: { azureQueries: [ { 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 e6d98f28da..62ca53d37e 100644 --- a/avm/res/automation/automation-account/software-update-configuration/main.json +++ b/avm/res/automation/automation-account/software-update-configuration/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "6467431009828483672" + "version": "0.26.54.24096", + "templateHash": "7586828544795723203" }, "name": "Automation Account Software Update Configurations", "description": "This module deploys an Azure Automation Account Software Update Configuration.", diff --git a/avm/res/automation/automation-account/tests/e2e/defaults/main.test.bicep b/avm/res/automation/automation-account/tests/e2e/defaults/main.test.bicep index 5f0a8e6212..80a79d90f5 100644 --- a/avm/res/automation/automation-account/tests/e2e/defaults/main.test.bicep +++ b/avm/res/automation/automation-account/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 +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 + } } -}] +] diff --git a/avm/res/automation/automation-account/tests/e2e/encr/dependencies.bicep b/avm/res/automation/automation-account/tests/e2e/encr/dependencies.bicep index c0fbbed613..49d0dfa3aa 100644 --- a/avm/res/automation/automation-account/tests/e2e/encr/dependencies.bicep +++ b/avm/res/automation/automation-account/tests/e2e/encr/dependencies.bicep @@ -8,44 +8,47 @@ param keyVaultName string param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { - name: keyVaultName - location: location - properties: { - sku: { - family: 'A' - name: 'standard' - } - tenantId: tenant().tenantId - softDeleteRetentionInDays: 7 - enablePurgeProtection: true - enabledForTemplateDeployment: true - enabledForDiskEncryption: true - enabledForDeployment: true - enableRbacAuthorization: true - accessPolicies: [] + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' } - - resource key 'keys@2022-07-01' = { - name: 'keyEncryptionKey' - properties: { - kty: 'RSA' - } + tenantId: tenant().tenantId + softDeleteRetentionInDays: 7 + enablePurgeProtection: true + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } + + resource key 'keys@2022-07-01' = { + name: 'keyEncryptionKey' + properties: { + kty: 'RSA' } + } } resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid('msi-${keyVault::key.id}-${location}-${managedIdentity.id}-Key-Reader-RoleAssignment') - scope: keyVault::key - properties: { - principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User - principalType: 'ServicePrincipal' - } + name: guid('msi-${keyVault::key.id}-${location}-${managedIdentity.id}-Key-Reader-RoleAssignment') + scope: keyVault::key + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '12338af0-0e69-4776-bea7-57ae8d297424' + ) // Key Vault Crypto User + principalType: 'ServicePrincipal' + } } @description('The resource ID of the created Key Vault.') diff --git a/avm/res/automation/automation-account/tests/e2e/encr/main.test.bicep b/avm/res/automation/automation-account/tests/e2e/encr/main.test.bicep index df5eef8136..c43435d4af 100644 --- a/avm/res/automation/automation-account/tests/e2e/encr/main.test.bicep +++ b/avm/res/automation/automation-account/tests/e2e/encr/main.test.bicep @@ -50,24 +50,26 @@ 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' - customerManagedKey: { - keyName: nestedDependencies.outputs.keyVaultEncryptionKeyName - keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - userAssignedIdentityResourceId: 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' + customerManagedKey: { + keyName: nestedDependencies.outputs.keyVaultEncryptionKeyName + keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + userAssignedIdentityResourceId: nestedDependencies.outputs.managedIdentityResourceId + } + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + location: resourceLocation } - managedIdentities: { - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - location: resourceLocation + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] 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 0c9b5a710d..e364a54391 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 @@ -56,220 +56,225 @@ 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' - diagnosticSettings: [ - { - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - gallerySolutions: [ - { - name: 'Updates' - product: 'OMSGallery' - publisher: 'Microsoft' - } - ] - jobSchedules: [ - { - runbookName: 'TestRunbook' - scheduleName: 'TestSchedule' - } - ] - disableLocalAuth: true - linkedWorkspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - location: resourceLocation - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - modules: [ - { - name: 'PSWindowsUpdate' - uri: 'https://www.powershellgallery.com/api/v2/package' - version: 'latest' - } - ] - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - service: 'Webhook' - subnetResourceId: nestedDependencies.outputs.customSubnet1ResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + diagnosticSettings: [ + { + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } - } - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - service: 'Webhook' - subnetResourceId: nestedDependencies.outputs.customSubnet2ResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + ] + gallerySolutions: [ + { + name: 'Updates' + product: 'OMSGallery' + publisher: 'Microsoft' } - } - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - service: 'DSCAndHybridWorker' - subnetResourceId: nestedDependencies.outputs.customSubnet1ResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + ] + jobSchedules: [ + { + runbookName: 'TestRunbook' + scheduleName: 'TestSchedule' } + ] + disableLocalAuth: true + linkedWorkspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + location: resourceLocation + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - 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' - } - ] - runbooks: [ - { - description: 'Test runbook' - name: 'TestRunbook' - type: 'PowerShell' - uri: 'https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/quickstarts/microsoft.automation/101-automation/scripts/AzureAutomationTutorial.ps1' - version: '1.0.0.0' - } - ] - schedules: [ - { - advancedSchedule: {} - expiryTime: '9999-12-31T13:00' - frequency: 'Hour' - interval: 12 - name: 'TestSchedule' - startTime: '' - timeZone: 'Europe/Berlin' - } - ] - softwareUpdateConfigurations: [ - { - excludeUpdates: [ - '123456' - ] - frequency: 'Month' - includeUpdates: [ - '654321' - ] - interval: 1 - maintenanceWindow: 'PT4H' - monthlyOccurrences: [ - { - day: 'Friday' - occurrence: 3 + modules: [ + { + name: 'PSWindowsUpdate' + uri: 'https://www.powershellgallery.com/api/v2/package' + version: 'latest' + } + ] + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + service: 'Webhook' + subnetResourceId: nestedDependencies.outputs.customSubnet1ResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - name: 'Windows_ZeroDay' - operatingSystem: 'Windows' - rebootSetting: 'IfRequired' - scopeByTags: { - Update: [ - 'Automatic-Wave1' + } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId ] + service: 'Webhook' + subnetResourceId: nestedDependencies.outputs.customSubnet2ResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } - startTime: '22:00' - updateClassifications: [ - 'Critical' - 'Definition' - 'FeaturePack' - 'Security' - 'ServicePack' - 'Tools' - 'UpdateRollup' - 'Updates' - ] - } - { - excludeUpdates: [ - 'icacls' - ] - frequency: 'OneTime' - includeUpdates: [ - 'kernel' - ] - maintenanceWindow: 'PT4H' - name: 'Linux_ZeroDay' - operatingSystem: 'Linux' - rebootSetting: 'IfRequired' - startTime: '22:00' - updateClassifications: [ - 'Critical' - 'Other' - 'Security' + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + service: 'DSCAndHybridWorker' + subnetResourceId: nestedDependencies.outputs.customSubnet1ResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + ] + 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' + } + ] + runbooks: [ + { + description: 'Test runbook' + name: 'TestRunbook' + type: 'PowerShell' + uri: 'https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/quickstarts/microsoft.automation/101-automation/scripts/AzureAutomationTutorial.ps1' + version: '1.0.0.0' + } + ] + schedules: [ + { + advancedSchedule: {} + expiryTime: '9999-12-31T13:00' + frequency: 'Hour' + interval: 12 + name: 'TestSchedule' + startTime: '' + timeZone: 'Europe/Berlin' + } + ] + softwareUpdateConfigurations: [ + { + excludeUpdates: [ + '123456' + ] + frequency: 'Month' + includeUpdates: [ + '654321' + ] + interval: 1 + maintenanceWindow: 'PT4H' + monthlyOccurrences: [ + { + day: 'Friday' + occurrence: 3 + } + ] + name: 'Windows_ZeroDay' + operatingSystem: 'Windows' + rebootSetting: 'IfRequired' + scopeByTags: { + Update: [ + 'Automatic-Wave1' + ] + } + startTime: '22:00' + updateClassifications: [ + 'Critical' + 'Definition' + 'FeaturePack' + 'Security' + 'ServicePack' + 'Tools' + 'UpdateRollup' + 'Updates' + ] + } + { + excludeUpdates: [ + 'icacls' + ] + frequency: 'OneTime' + includeUpdates: [ + 'kernel' + ] + maintenanceWindow: 'PT4H' + name: 'Linux_ZeroDay' + operatingSystem: 'Linux' + rebootSetting: 'IfRequired' + startTime: '22:00' + updateClassifications: [ + 'Critical' + 'Other' + 'Security' + ] + } + ] + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId ] } - ] - managedIdentities: { - systemAssigned: true - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId + variables: [ + { + description: 'TestStringDescription' + name: 'TestString' + value: '\'TestString\'' + } + { + description: 'TestIntegerDescription' + name: 'TestInteger' + value: '500' + } + { + description: 'TestBooleanDescription' + name: 'TestBoolean' + value: 'false' + } + { + description: 'TestDateTimeDescription' + isEncrypted: false + name: 'TestDateTime' + value: '\'\\/Date(1637934042656)\\/\'' + } + { + description: 'TestEncryptedDescription' + name: 'TestEncryptedVariable' + value: '\'TestEncryptedValue\'' + } ] - } - variables: [ - { - description: 'TestStringDescription' - name: 'TestString' - value: '\'TestString\'' - } - { - description: 'TestIntegerDescription' - name: 'TestInteger' - value: '500' - } - { - description: 'TestBooleanDescription' - name: 'TestBoolean' - value: 'false' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - { - description: 'TestDateTimeDescription' - isEncrypted: false - name: 'TestDateTime' - value: '\'\\/Date(1637934042656)\\/\'' - } - { - description: 'TestEncryptedDescription' - name: 'TestEncryptedVariable' - value: '\'TestEncryptedValue\'' - } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] 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 d2bbfb2033..d6182ea498 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 @@ -60,190 +60,192 @@ 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' - diagnosticSettings: [ - { - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - gallerySolutions: [ - { - name: 'Updates' - product: 'OMSGallery' - publisher: 'Microsoft' - } - ] - jobSchedules: [ - { - runbookName: 'TestRunbook' - scheduleName: 'TestSchedule' - } - ] - disableLocalAuth: true - linkedWorkspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - location: resourceLocation - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - modules: [ - { - name: 'PSWindowsUpdate' - uri: 'https://www.powershellgallery.com/api/v2/package' - version: 'latest' - } - ] - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - service: 'Webhook' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + diagnosticSettings: [ + { + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } - } - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - service: 'DSCAndHybridWorker' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + ] + gallerySolutions: [ + { + name: 'Updates' + product: 'OMSGallery' + publisher: 'Microsoft' } + ] + jobSchedules: [ + { + runbookName: 'TestRunbook' + scheduleName: 'TestSchedule' + } + ] + disableLocalAuth: true + linkedWorkspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + location: resourceLocation + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - runbooks: [ - { - description: 'Test runbook' - name: 'TestRunbook' - type: 'PowerShell' - uri: 'https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/quickstarts/microsoft.automation/101-automation/scripts/AzureAutomationTutorial.ps1' - version: '1.0.0.0' - } - ] - schedules: [ - { - advancedSchedule: {} - expiryTime: '9999-12-31T13:00' - frequency: 'Hour' - interval: 12 - name: 'TestSchedule' - startTime: '' - timeZone: 'Europe/Berlin' - } - ] - softwareUpdateConfigurations: [ - { - excludeUpdates: [ - '123456' - ] - frequency: 'Month' - includeUpdates: [ - '654321' - ] - interval: 1 - maintenanceWindow: 'PT4H' - monthlyOccurrences: [ - { - day: 'Friday' - occurrence: 3 + modules: [ + { + name: 'PSWindowsUpdate' + uri: 'https://www.powershellgallery.com/api/v2/package' + version: 'latest' + } + ] + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + service: 'Webhook' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - name: 'Windows_ZeroDay' - operatingSystem: 'Windows' - rebootSetting: 'IfRequired' - scopeByTags: { - Update: [ - 'Automatic-Wave1' + } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId ] + service: 'DSCAndHybridWorker' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } - startTime: '22:00' - updateClassifications: [ - 'Critical' - 'Definition' - 'FeaturePack' - 'Security' - 'ServicePack' - 'Tools' - 'UpdateRollup' - 'Updates' - ] - } - { - excludeUpdates: [ - 'icacls' - ] - frequency: 'OneTime' - includeUpdates: [ - 'kernel' - ] - maintenanceWindow: 'PT4H' - name: 'Linux_ZeroDay' - operatingSystem: 'Linux' - rebootSetting: 'IfRequired' - startTime: '22:00' - updateClassifications: [ - 'Critical' - 'Other' - 'Security' + ] + runbooks: [ + { + description: 'Test runbook' + name: 'TestRunbook' + type: 'PowerShell' + uri: 'https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/quickstarts/microsoft.automation/101-automation/scripts/AzureAutomationTutorial.ps1' + version: '1.0.0.0' + } + ] + schedules: [ + { + advancedSchedule: {} + expiryTime: '9999-12-31T13:00' + frequency: 'Hour' + interval: 12 + name: 'TestSchedule' + startTime: '' + timeZone: 'Europe/Berlin' + } + ] + softwareUpdateConfigurations: [ + { + excludeUpdates: [ + '123456' + ] + frequency: 'Month' + includeUpdates: [ + '654321' + ] + interval: 1 + maintenanceWindow: 'PT4H' + monthlyOccurrences: [ + { + day: 'Friday' + occurrence: 3 + } + ] + name: 'Windows_ZeroDay' + operatingSystem: 'Windows' + rebootSetting: 'IfRequired' + scopeByTags: { + Update: [ + 'Automatic-Wave1' + ] + } + startTime: '22:00' + updateClassifications: [ + 'Critical' + 'Definition' + 'FeaturePack' + 'Security' + 'ServicePack' + 'Tools' + 'UpdateRollup' + 'Updates' + ] + } + { + excludeUpdates: [ + 'icacls' + ] + frequency: 'OneTime' + includeUpdates: [ + 'kernel' + ] + maintenanceWindow: 'PT4H' + name: 'Linux_ZeroDay' + operatingSystem: 'Linux' + rebootSetting: 'IfRequired' + startTime: '22:00' + updateClassifications: [ + 'Critical' + 'Other' + 'Security' + ] + } + ] + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId ] } - ] - managedIdentities: { - systemAssigned: true - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId + variables: [ + { + description: 'TestStringDescription' + name: 'TestString' + value: '\'TestString\'' + } + { + description: 'TestIntegerDescription' + name: 'TestInteger' + value: '500' + } + { + description: 'TestBooleanDescription' + name: 'TestBoolean' + value: 'false' + } + { + description: 'TestDateTimeDescription' + name: 'TestDateTime' + value: '\'\\/Date(1637934042656)\\/\'' + } + { + description: 'TestEncryptedDescription' + name: 'TestEncryptedVariable' + value: '\'TestEncryptedValue\'' + } ] - } - variables: [ - { - description: 'TestStringDescription' - name: 'TestString' - value: '\'TestString\'' - } - { - description: 'TestIntegerDescription' - name: 'TestInteger' - value: '500' - } - { - description: 'TestBooleanDescription' - name: 'TestBoolean' - value: 'false' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - { - description: 'TestDateTimeDescription' - name: 'TestDateTime' - value: '\'\\/Date(1637934042656)\\/\'' - } - { - description: 'TestEncryptedDescription' - name: 'TestEncryptedVariable' - value: '\'TestEncryptedValue\'' - } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/automation/automation-account/variable/main.json b/avm/res/automation/automation-account/variable/main.json index ec55c87f17..a7d20d69f2 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.25.53.49325", - "templateHash": "15605588341437540157" + "version": "0.26.54.24096", + "templateHash": "1065450815403209329" }, "name": "Automation Account Variables", "description": "This module deploys an Azure Automation Account Variable.", diff --git a/avm/res/cdn/profile/afdEndpoint/main.bicep b/avm/res/cdn/profile/afdEndpoint/main.bicep index 2e915b62ea..b4097732bc 100644 --- a/avm/res/cdn/profile/afdEndpoint/main.bicep +++ b/avm/res/cdn/profile/afdEndpoint/main.bicep @@ -48,25 +48,27 @@ resource afdEndpoint 'Microsoft.Cdn/profiles/afdEndpoints@2023-05-01' = { } } -module afdEndpoint_routes 'route/main.bicep' = [for route in (routes ?? []): { - name: '${uniqueString(deployment().name, route.name)}-Profile-AfdEndpoint-Route' - params: { - name: route.name - profileName: profile.name - afdEndpointName: afdEndpoint.name - cacheConfiguration: route.?cacheConfiguration - customDomainName: route.?customDomainName - enabledState: route.?enabledState - forwardingProtocol: route.?forwardingProtocol - httpsRedirect: route.?httpsRedirect - linkToDefaultDomain: route.?linkToDefaultDomain - originGroupName: route.?originGroupName - originPath: route.?originPath - patternsToMatch: route.?patternsToMatch - ruleSets: route.?ruleSets - supportedProtocols: route.?supportedProtocols +module afdEndpoint_routes 'route/main.bicep' = [ + for route in (routes ?? []): { + name: '${uniqueString(deployment().name, route.name)}-Profile-AfdEndpoint-Route' + params: { + name: route.name + profileName: profile.name + afdEndpointName: afdEndpoint.name + cacheConfiguration: route.?cacheConfiguration + customDomainName: route.?customDomainName + enabledState: route.?enabledState + forwardingProtocol: route.?forwardingProtocol + httpsRedirect: route.?httpsRedirect + linkToDefaultDomain: route.?linkToDefaultDomain + originGroupName: route.?originGroupName + originPath: route.?originPath + patternsToMatch: route.?patternsToMatch + ruleSets: route.?ruleSets + supportedProtocols: route.?supportedProtocols + } } -}] +] @description('The name of the AFD Endpoint.') output name string = afdEndpoint.name diff --git a/avm/res/cdn/profile/afdEndpoint/main.json b/avm/res/cdn/profile/afdEndpoint/main.json index 8d680f92d5..dbaf3c9233 100644 --- a/avm/res/cdn/profile/afdEndpoint/main.json +++ b/avm/res/cdn/profile/afdEndpoint/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "694786816081848742" + "version": "0.26.54.24096", + "templateHash": "8869132357079269087" }, "name": "CDN Profiles AFD Endpoints", "description": "This module deploys a CDN Profile AFD Endpoint.", @@ -156,8 +156,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16844846729595835268" + "version": "0.26.54.24096", + "templateHash": "8525791914559803218" }, "name": "CDN Profiles AFD Endpoint Route", "description": "This module deploys a CDN Profile AFD Endpoint route.", diff --git a/avm/res/cdn/profile/afdEndpoint/route/main.bicep b/avm/res/cdn/profile/afdEndpoint/route/main.bicep index 072eeae74d..a18fa37fb2 100644 --- a/avm/res/cdn/profile/afdEndpoint/route/main.bicep +++ b/avm/res/cdn/profile/afdEndpoint/route/main.bicep @@ -58,7 +58,7 @@ param patternsToMatch array? @description('Optional. The rule sets of the rule. The rule sets must be defined in the profile ruleSets.') param ruleSets array = [] -@allowed([ 'Http', 'Https' ]) +@allowed(['Http', 'Https']) @description('Optional. The supported protocols of the rule.') param supportedProtocols array? @@ -69,17 +69,20 @@ resource profile 'Microsoft.Cdn/profiles@2023-05-01' existing = { name: afdEndpointName } - resource customDomain 'customDomains@2023-05-01' existing = if (!empty(customDomainName)) { - name: customDomainName ?? '' - } + resource customDomain 'customDomains@2023-05-01' existing = + if (!empty(customDomainName)) { + name: customDomainName ?? '' + } resource originGroup 'originGroups@2023-05-01' existing = { name: originGroupName } - resource ruleSet 'ruleSets@2023-05-01' existing = [for ruleSet in ruleSets: { - name: ruleSet.name - }] + resource ruleSet 'ruleSets@2023-05-01' existing = [ + for ruleSet in ruleSets: { + name: ruleSet.name + } + ] } resource route 'Microsoft.Cdn/profiles/afdEndpoints/routes@2023-05-01' = { @@ -87,9 +90,13 @@ resource route 'Microsoft.Cdn/profiles/afdEndpoints/routes@2023-05-01' = { parent: profile::afdEndpoint properties: { cacheConfiguration: cacheConfiguration - customDomains: !empty(customDomainName) ? [ { - id: profile::customDomain.id - } ] : [] + customDomains: !empty(customDomainName) + ? [ + { + id: profile::customDomain.id + } + ] + : [] enabledState: enabledState forwardingProtocol: forwardingProtocol httpsRedirect: httpsRedirect @@ -99,9 +106,11 @@ resource route 'Microsoft.Cdn/profiles/afdEndpoints/routes@2023-05-01' = { } originPath: originPath patternsToMatch: patternsToMatch - ruleSets: [for (item, index) in ruleSets: { - id: profile::ruleSet[index].id - }] + ruleSets: [ + for (item, index) in ruleSets: { + id: profile::ruleSet[index].id + } + ] supportedProtocols: supportedProtocols } } diff --git a/avm/res/cdn/profile/afdEndpoint/route/main.json b/avm/res/cdn/profile/afdEndpoint/route/main.json index a57d1b974f..ce9f9ea2c5 100644 --- a/avm/res/cdn/profile/afdEndpoint/route/main.json +++ b/avm/res/cdn/profile/afdEndpoint/route/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16844846729595835268" + "version": "0.26.54.24096", + "templateHash": "8525791914559803218" }, "name": "CDN Profiles AFD Endpoint Route", "description": "This module deploys a CDN Profile AFD Endpoint route.", diff --git a/avm/res/cdn/profile/customdomain/main.bicep b/avm/res/cdn/profile/customdomain/main.bicep index 22eafb347f..a0a4f4477f 100644 --- a/avm/res/cdn/profile/customdomain/main.bicep +++ b/avm/res/cdn/profile/customdomain/main.bicep @@ -40,29 +40,36 @@ 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' = { name: name parent: profile properties: { - azureDnsZone: !empty(azureDnsZoneResourceId) ? { - id: azureDnsZoneResourceId - } : null + azureDnsZone: !empty(azureDnsZoneResourceId) + ? { + id: azureDnsZoneResourceId + } + : null extendedProperties: !empty(extendedProperties) ? extendedProperties : null hostName: hostName - preValidatedCustomDomainResourceId: !empty(preValidatedCustomDomainResourceId) ? { - id: preValidatedCustomDomainResourceId - } : null + preValidatedCustomDomainResourceId: !empty(preValidatedCustomDomainResourceId) + ? { + id: preValidatedCustomDomainResourceId + } + : null tlsSettings: { certificateType: certificateType minimumTlsVersion: minimumTlsVersion - secret: !(empty(secretName)) ? { - id: profile::secrect.id - } : null + secret: !(empty(secretName)) + ? { + id: profile::secrect.id + } + : null } } } diff --git a/avm/res/cdn/profile/customdomain/main.json b/avm/res/cdn/profile/customdomain/main.json index 1f9c03364e..54f6fa7a8d 100644 --- a/avm/res/cdn/profile/customdomain/main.json +++ b/avm/res/cdn/profile/customdomain/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14057037772702090927" + "version": "0.26.54.24096", + "templateHash": "15657388199001378642" }, "name": "CDN Profiles Custom Domains", "description": "This module deploys a CDN Profile Custom Domains.", diff --git a/avm/res/cdn/profile/endpoint/main.bicep b/avm/res/cdn/profile/endpoint/main.bicep index c5fcaadb99..2379bba4d0 100644 --- a/avm/res/cdn/profile/endpoint/main.bicep +++ b/avm/res/cdn/profile/endpoint/main.bicep @@ -29,24 +29,26 @@ resource endpoint 'microsoft.cdn/profiles/endpoints@2021-06-01' = { tags: tags } -module endpoint_origins 'origin/main.bicep' = [for origin in properties.origins: { - name: '${name}-origins-${origin.name}' - params: { - profileName: profile.name - endpointName: endpoint.name - name: origin.name - hostName: origin.properties.hostName - httpPort: origin.properties.?httpPort - httpsPort: origin.properties.?httpsPort - enabled: origin.properties.enabled - priority: origin.properties.?priority - weight: origin.properties.?weight - originHostHeader: origin.properties.?originHostHeader - privateLinkAlias: origin.properties.?privateLinkAlias - privateLinkLocation: origin.properties.?privateLinkLocation - privateLinkResourceId: origin.properties.?privateLinkResourceId +module endpoint_origins 'origin/main.bicep' = [ + for origin in properties.origins: { + name: '${name}-origins-${origin.name}' + params: { + profileName: profile.name + endpointName: endpoint.name + name: origin.name + hostName: origin.properties.hostName + httpPort: origin.properties.?httpPort + httpsPort: origin.properties.?httpsPort + enabled: origin.properties.enabled + priority: origin.properties.?priority + weight: origin.properties.?weight + originHostHeader: origin.properties.?originHostHeader + privateLinkAlias: origin.properties.?privateLinkAlias + privateLinkLocation: origin.properties.?privateLinkLocation + privateLinkResourceId: origin.properties.?privateLinkResourceId + } } -}] +] @description('The name of the endpoint.') output name string = endpoint.name diff --git a/avm/res/cdn/profile/endpoint/main.json b/avm/res/cdn/profile/endpoint/main.json index e0e3dcc3a3..4866a4cf53 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.25.53.49325", - "templateHash": "12552673613712108877" + "version": "0.26.54.24096", + "templateHash": "5516612458443504281" }, "name": "CDN Profiles Endpoints", "description": "This module deploys a CDN Profile Endpoint.", @@ -125,8 +125,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17135058845123401414" + "version": "0.26.54.24096", + "templateHash": "11112660703037023992" }, "name": "CDN Profiles Endpoints Origins", "description": "This module deploys a CDN Profile Endpoint Origin.", diff --git a/avm/res/cdn/profile/endpoint/origin/main.bicep b/avm/res/cdn/profile/endpoint/origin/main.bicep index 18a571818d..74a9076547 100644 --- a/avm/res/cdn/profile/endpoint/origin/main.bicep +++ b/avm/res/cdn/profile/endpoint/origin/main.bicep @@ -53,22 +53,36 @@ resource endpoint 'Microsoft.Cdn/profiles/endpoints@2021-06-01' existing = { resource origin 'Microsoft.Cdn/profiles/endpoints/origins@2021-06-01' = { parent: endpoint name: name - properties: union({ + properties: union( + { hostName: hostName httpPort: httpPort enabled: enabled httpsPort: httpsPort - }, ((priority > 0 || weight > 0) ? { - priority: priority - weight: weight - } : {}), (!empty(privateLinkAlias) && !empty(privateLinkLocation) ? { - privateLinkAlias: privateLinkAlias - privateLinkLocation: privateLinkLocation - } : {}), (!empty(privateLinkResourceId) ? { - privateLinkResourceId: privateLinkResourceId - } : {}), (!empty(originHostHeader) ? { - originHostHeader: originHostHeader - } : {})) + }, + ((priority > 0 || weight > 0) + ? { + priority: priority + weight: weight + } + : {}), + (!empty(privateLinkAlias) && !empty(privateLinkLocation) + ? { + privateLinkAlias: privateLinkAlias + privateLinkLocation: privateLinkLocation + } + : {}), + (!empty(privateLinkResourceId) + ? { + privateLinkResourceId: privateLinkResourceId + } + : {}), + (!empty(originHostHeader) + ? { + originHostHeader: originHostHeader + } + : {}) + ) } @description('The name of the endpoint.') diff --git a/avm/res/cdn/profile/endpoint/origin/main.json b/avm/res/cdn/profile/endpoint/origin/main.json index 8604bb0323..bb4eefa74d 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.25.53.49325", - "templateHash": "17135058845123401414" + "version": "0.26.54.24096", + "templateHash": "11112660703037023992" }, "name": "CDN Profiles Endpoints Origins", "description": "This module deploys a CDN Profile Endpoint Origin.", diff --git a/avm/res/cdn/profile/main.bicep b/avm/res/cdn/profile/main.bicep index 3ea5c23fa9..27d05ae8c1 100644 --- a/avm/res/cdn/profile/main.bicep +++ b/avm/res/cdn/profile/main.bicep @@ -63,34 +63,53 @@ param roleAssignments roleAssignmentType param enableTelemetry bool = true var builtInRoleNames = { - 'CDN Endpoint Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '426e0c7f-0c7e-4658-b36f-ff54d6c29b45') - 'CDN Endpoint Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '871e35f6-b5c1-49cc-a043-bde969a0f2cd') - 'CDN Profile Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ec156ff8-a8d1-4d15-830c-5b80698ca432') - 'CDN Profile Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f96442b-4075-438f-813d-ad51ab4019af') + 'CDN Endpoint Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '426e0c7f-0c7e-4658-b36f-ff54d6c29b45' + ) + 'CDN Endpoint Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '871e35f6-b5c1-49cc-a043-bde969a0f2cd' + ) + 'CDN Profile Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'ec156ff8-a8d1-4d15-830c-5b80698ca432' + ) + 'CDN Profile Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '8f96442b-4075-438f-813d-ad51ab4019af' + ) 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.cdn-profile.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.cdn-profile.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource profile 'Microsoft.Cdn/profiles@2023-05-01' = { name: name @@ -104,109 +123,129 @@ resource profile 'Microsoft.Cdn/profiles@2023-05-01' = { tags: tags } -resource profile_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.' +resource profile_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: profile } - scope: profile -} -resource profile_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(profile.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource profile_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(profile.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: profile } - scope: profile -}] - -module profile_endpoint 'endpoint/main.bicep' = if (!empty(endpointProperties)) { - name: '${uniqueString(deployment().name, location)}-Profile-Endpoint' - params: { - name: endpointName ?? '${profile.name}-endpoint' - properties: endpointProperties ?? {} - location: location - profileName: profile.name +] + +module profile_endpoint 'endpoint/main.bicep' = + if (!empty(endpointProperties)) { + name: '${uniqueString(deployment().name, location)}-Profile-Endpoint' + params: { + name: endpointName ?? '${profile.name}-endpoint' + properties: endpointProperties ?? {} + location: location + profileName: profile.name + } } -} -module profile_secrets 'secret/main.bicep' = [for (secret, index) in secrets: { - name: '${uniqueString(deployment().name)}-Profile-Secret-${index}' - params: { - name: secret.name - profileName: profile.name - type: secret.type - secretSourceResourceId: secret.secretSourceResourceId - subjectAlternativeNames: secret.?subjectAlternativeNames - useLatestVersion: secret.?useLatestVersion - secretVersion: secret.secretVersion +module profile_secrets 'secret/main.bicep' = [ + for (secret, index) in secrets: { + name: '${uniqueString(deployment().name)}-Profile-Secret-${index}' + params: { + name: secret.name + profileName: profile.name + type: secret.type + secretSourceResourceId: secret.secretSourceResourceId + subjectAlternativeNames: secret.?subjectAlternativeNames + useLatestVersion: secret.?useLatestVersion + secretVersion: secret.secretVersion + } } -}] - -module profile_customDomains 'customdomain/main.bicep' = [for (customDomain, index) in customDomains: { - name: '${uniqueString(deployment().name)}-CustomDomain-${index}' - dependsOn: [ - profile_secrets - ] - params: { - name: customDomain.name - profileName: profile.name - hostName: customDomain.hostName - azureDnsZoneResourceId: customDomain.?azureDnsZoneResourceId - extendedProperties: customDomain.?extendedProperties - certificateType: customDomain.certificateType - minimumTlsVersion: customDomain.?minimumTlsVersion - preValidatedCustomDomainResourceId: customDomain.?preValidatedCustomDomainResourceId - secretName: customDomain.?secretName +] + +module profile_customDomains 'customdomain/main.bicep' = [ + for (customDomain, index) in customDomains: { + name: '${uniqueString(deployment().name)}-CustomDomain-${index}' + dependsOn: [ + profile_secrets + ] + params: { + name: customDomain.name + profileName: profile.name + hostName: customDomain.hostName + azureDnsZoneResourceId: customDomain.?azureDnsZoneResourceId + extendedProperties: customDomain.?extendedProperties + certificateType: customDomain.certificateType + minimumTlsVersion: customDomain.?minimumTlsVersion + preValidatedCustomDomainResourceId: customDomain.?preValidatedCustomDomainResourceId + secretName: customDomain.?secretName + } } -}] - -module profile_originGroups 'origingroup/main.bicep' = [for (origingroup, index) in origionGroups: { - name: '${uniqueString(deployment().name)}-Profile-OrigionGroup-${index}' - params: { - name: origingroup.name - profileName: profile.name - loadBalancingSettings: origingroup.loadBalancingSettings - healthProbeSettings: origingroup.?healthProbeSettings - sessionAffinityState: origingroup.?sessionAffinityState - trafficRestorationTimeToHealedOrNewEndpointsInMinutes: origingroup.?trafficRestorationTimeToHealedOrNewEndpointsInMinutes - origins: origingroup.origins +] + +module profile_originGroups 'origingroup/main.bicep' = [ + for (origingroup, index) in origionGroups: { + name: '${uniqueString(deployment().name)}-Profile-OrigionGroup-${index}' + params: { + name: origingroup.name + profileName: profile.name + loadBalancingSettings: origingroup.loadBalancingSettings + healthProbeSettings: origingroup.?healthProbeSettings + sessionAffinityState: origingroup.?sessionAffinityState + trafficRestorationTimeToHealedOrNewEndpointsInMinutes: origingroup.?trafficRestorationTimeToHealedOrNewEndpointsInMinutes + origins: origingroup.origins + } } -}] - -module profile_ruleSets 'ruleset/main.bicep' = [for (ruleSet, index) in ruleSets: { - name: '${uniqueString(deployment().name)}-Profile-RuleSet-${index}' - params: { - name: ruleSet.name - profileName: profile.name - rules: ruleSet.rules +] + +module profile_ruleSets 'ruleset/main.bicep' = [ + for (ruleSet, index) in ruleSets: { + name: '${uniqueString(deployment().name)}-Profile-RuleSet-${index}' + params: { + name: ruleSet.name + profileName: profile.name + rules: ruleSet.rules + } } -}] - -module profile_afdEndpoints 'afdEndpoint/main.bicep' = [for (afdEndpoint, index) in afdEndpoints: { - name: '${uniqueString(deployment().name)}-Profile-AfdEndpoint-${index}' - dependsOn: [ - profile_originGroups - profile_customDomains - profile_ruleSets - ] - params: { - name: afdEndpoint.name - location: location - profileName: profile.name - autoGeneratedDomainNameLabelScope: afdEndpoint.?autoGeneratedDomainNameLabelScope - enabledState: afdEndpoint.?enabledState - routes: afdEndpoint.?routes - tags: afdEndpoint.?tags ?? tags +] + +module profile_afdEndpoints 'afdEndpoint/main.bicep' = [ + for (afdEndpoint, index) in afdEndpoints: { + name: '${uniqueString(deployment().name)}-Profile-AfdEndpoint-${index}' + dependsOn: [ + profile_originGroups + profile_customDomains + profile_ruleSets + ] + params: { + name: afdEndpoint.name + location: location + profileName: profile.name + autoGeneratedDomainNameLabelScope: afdEndpoint.?autoGeneratedDomainNameLabelScope + enabledState: afdEndpoint.?enabledState + routes: afdEndpoint.?routes + tags: afdEndpoint.?tags ?? tags + } } -}] +] @description('The name of the CDN profile.') output name string = profile.name diff --git a/avm/res/cdn/profile/main.json b/avm/res/cdn/profile/main.json index 81acb14639..c0f0f30a68 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.25.53.49325", - "templateHash": "5590822157258383721" + "version": "0.26.54.24096", + "templateHash": "9474385640753599051" }, "name": "CDN Profiles", "description": "This module deploys a CDN Profile.", @@ -337,8 +337,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "12552673613712108877" + "version": "0.26.54.24096", + "templateHash": "5516612458443504281" }, "name": "CDN Profiles Endpoints", "description": "This module deploys a CDN Profile Endpoint.", @@ -457,8 +457,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17135058845123401414" + "version": "0.26.54.24096", + "templateHash": "11112660703037023992" }, "name": "CDN Profiles Endpoints Origins", "description": "This module deploys a CDN Profile Endpoint Origin.", @@ -703,8 +703,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3645784765890890733" + "version": "0.26.54.24096", + "templateHash": "7298174434641608123" }, "name": "CDN Profiles Secret", "description": "This module deploys a CDN Profile Secret.", @@ -852,8 +852,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14057037772702090927" + "version": "0.26.54.24096", + "templateHash": "15657388199001378642" }, "name": "CDN Profiles Custom Domains", "description": "This module deploys a CDN Profile Custom Domains.", @@ -1019,8 +1019,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "8675132561244182118" + "version": "0.26.54.24096", + "templateHash": "8706007645911322422" }, "name": "CDN Profiles Origin Group", "description": "This module deploys a CDN Profile Origin Group.", @@ -1156,8 +1156,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17323276561210856523" + "version": "0.26.54.24096", + "templateHash": "16657064743499074369" }, "name": "CDN Profiles Origin", "description": "This module deploys a CDN Profile Origin.", @@ -1382,8 +1382,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4615747470717464878" + "version": "0.26.54.24096", + "templateHash": "1809010747275335698" }, "name": "CDN Profiles Rule Sets", "description": "This module deploys a CDN Profile rule set.", @@ -1468,8 +1468,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "9936176531232217343" + "version": "0.26.54.24096", + "templateHash": "8195283154733773558" }, "name": "CDN Profiles Rules", "description": "This module deploys a CDN Profile rule.", @@ -1656,8 +1656,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "694786816081848742" + "version": "0.26.54.24096", + "templateHash": "8869132357079269087" }, "name": "CDN Profiles AFD Endpoints", "description": "This module deploys a CDN Profile AFD Endpoint.", @@ -1807,8 +1807,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16844846729595835268" + "version": "0.26.54.24096", + "templateHash": "8525791914559803218" }, "name": "CDN Profiles AFD Endpoint Route", "description": "This module deploys a CDN Profile AFD Endpoint route.", diff --git a/avm/res/cdn/profile/origingroup/main.bicep b/avm/res/cdn/profile/origingroup/main.bicep index adc29691b5..258f75686f 100644 --- a/avm/res/cdn/profile/origingroup/main.bicep +++ b/avm/res/cdn/profile/origingroup/main.bicep @@ -42,23 +42,25 @@ resource originGroup 'Microsoft.Cdn/profiles/originGroups@2023-05-01' = { } } -module originGroup_origins 'origin/main.bicep' = [for (origin, index) in origins: { - name: '${uniqueString(deployment().name)}-OriginGroup-Origin-${index}' - params: { - name: origin.name - profileName: profileName - hostName: origin.hostName - originGroupName: originGroup.name - enabledState: origin.?enabledState - enforceCertificateNameCheck: origin.?enforceCertificateNameCheck - httpPort: origin.?httpPort - httpsPort: origin.?httpsPort - originHostHeader: origin.?originHostHeader ?? origin.hostName - priority: origin.?priority - weight: origin.?weight - sharedPrivateLinkResource: origin.?sharedPrivateLinkResource +module originGroup_origins 'origin/main.bicep' = [ + for (origin, index) in origins: { + name: '${uniqueString(deployment().name)}-OriginGroup-Origin-${index}' + params: { + name: origin.name + profileName: profileName + hostName: origin.hostName + originGroupName: originGroup.name + enabledState: origin.?enabledState + enforceCertificateNameCheck: origin.?enforceCertificateNameCheck + httpPort: origin.?httpPort + httpsPort: origin.?httpsPort + originHostHeader: origin.?originHostHeader ?? origin.hostName + priority: origin.?priority + weight: origin.?weight + sharedPrivateLinkResource: origin.?sharedPrivateLinkResource + } } -}] +] @description('The name of the origin group.') output name string = originGroup.name diff --git a/avm/res/cdn/profile/origingroup/main.json b/avm/res/cdn/profile/origingroup/main.json index a2f6cb1d54..4dce9e8ca3 100644 --- a/avm/res/cdn/profile/origingroup/main.json +++ b/avm/res/cdn/profile/origingroup/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "8675132561244182118" + "version": "0.26.54.24096", + "templateHash": "8706007645911322422" }, "name": "CDN Profiles Origin Group", "description": "This module deploys a CDN Profile Origin Group.", @@ -142,8 +142,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17323276561210856523" + "version": "0.26.54.24096", + "templateHash": "16657064743499074369" }, "name": "CDN Profiles Origin", "description": "This module deploys a CDN Profile Origin.", diff --git a/avm/res/cdn/profile/origingroup/origin/main.json b/avm/res/cdn/profile/origingroup/origin/main.json index 1988abc0e8..fb48ec8744 100644 --- a/avm/res/cdn/profile/origingroup/origin/main.json +++ b/avm/res/cdn/profile/origingroup/origin/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17323276561210856523" + "version": "0.26.54.24096", + "templateHash": "16657064743499074369" }, "name": "CDN Profiles Origin", "description": "This module deploys a CDN Profile Origin.", diff --git a/avm/res/cdn/profile/ruleset/main.bicep b/avm/res/cdn/profile/ruleset/main.bicep index c62e53d469..9d96381236 100644 --- a/avm/res/cdn/profile/ruleset/main.bicep +++ b/avm/res/cdn/profile/ruleset/main.bicep @@ -20,18 +20,20 @@ resource ruleSet 'Microsoft.Cdn/profiles/ruleSets@2023-05-01' = { parent: profile } -module ruleSet_rules 'rule/main.bicep' = [for (rule, index) in (rules ?? []): { - name: '${uniqueString(deployment().name)}-RuleSet-Rule-${rule.name}-${index}' - params: { - profileName: profileName - ruleSetName: name - name: rule.name - order: rule.order - actions: rule.?actions - conditions: rule.?conditions - matchProcessingBehavior: rule.?matchProcessingBehavior +module ruleSet_rules 'rule/main.bicep' = [ + for (rule, index) in (rules ?? []): { + name: '${uniqueString(deployment().name)}-RuleSet-Rule-${rule.name}-${index}' + params: { + profileName: profileName + ruleSetName: name + name: rule.name + order: rule.order + actions: rule.?actions + conditions: rule.?conditions + matchProcessingBehavior: rule.?matchProcessingBehavior + } } -}] +] @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 7220e258e3..349d081644 100644 --- a/avm/res/cdn/profile/ruleset/main.json +++ b/avm/res/cdn/profile/ruleset/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4615747470717464878" + "version": "0.26.54.24096", + "templateHash": "1809010747275335698" }, "name": "CDN Profiles Rule Sets", "description": "This module deploys a CDN Profile rule set.", @@ -91,8 +91,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "9936176531232217343" + "version": "0.26.54.24096", + "templateHash": "8195283154733773558" }, "name": "CDN Profiles Rules", "description": "This module deploys a CDN Profile rule.", diff --git a/avm/res/cdn/profile/ruleset/rule/main.json b/avm/res/cdn/profile/ruleset/rule/main.json index 2d3057f19b..dc817e69f6 100644 --- a/avm/res/cdn/profile/ruleset/rule/main.json +++ b/avm/res/cdn/profile/ruleset/rule/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "9936176531232217343" + "version": "0.26.54.24096", + "templateHash": "8195283154733773558" }, "name": "CDN Profiles Rules", "description": "This module deploys a CDN Profile rule.", diff --git a/avm/res/cdn/profile/secret/main.bicep b/avm/res/cdn/profile/secret/main.bicep index 29cd8dbe71..1f910147e8 100644 --- a/avm/res/cdn/profile/secret/main.bicep +++ b/avm/res/cdn/profile/secret/main.bicep @@ -38,15 +38,17 @@ resource secret 'Microsoft.Cdn/profiles/secrets@2023-05-01' = { name: name parent: profile properties: { - parameters: (type == 'CustomerCertificate') ? { - type: type - secretSource: { - id: secretSourceResourceId - } - secretVersion: secretVersion - subjectAlternativeNames: subjectAlternativeNames - useLatestVersion: useLatestVersion - } : null + parameters: (type == 'CustomerCertificate') + ? { + type: type + secretSource: { + id: secretSourceResourceId + } + secretVersion: secretVersion + subjectAlternativeNames: subjectAlternativeNames + useLatestVersion: useLatestVersion + } + : null } } diff --git a/avm/res/cdn/profile/secret/main.json b/avm/res/cdn/profile/secret/main.json index 657d94853b..9ba045e7be 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.25.53.49325", - "templateHash": "3645784765890890733" + "version": "0.26.54.24096", + "templateHash": "7298174434641608123" }, "name": "CDN Profiles Secret", "description": "This module deploys a CDN Profile Secret.", diff --git a/avm/res/cdn/profile/tests/e2e/afd/main.test.bicep b/avm/res/cdn/profile/tests/e2e/afd/main.test.bicep index 6394e8e2ae..b559a41236 100644 --- a/avm/res/cdn/profile/tests/e2e/afd/main.test.bicep +++ b/avm/res/cdn/profile/tests/e2e/afd/main.test.bicep @@ -36,76 +36,78 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - name: 'dep-${namePrefix}-test-${serviceShort}' - location: 'global' - originResponseTimeoutSeconds: 60 - sku: 'Standard_AzureFrontDoor' - customDomains: [ - { - name: 'dep-${namePrefix}-test-${serviceShort}-custom-domain' - hostName: 'dep-${namePrefix}-test-${serviceShort}-custom-domain.azurewebsites.net' - certificateType: 'ManagedCertificate' - } - ] - origionGroups: [ - { - name: 'dep-${namePrefix}-test-${serviceShort}-origin-group' - loadBalancingSettings: { - additionalLatencyInMilliseconds: 50 - sampleSize: 4 - successfulSamplesRequired: 3 +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: 'dep-${namePrefix}-test-${serviceShort}' + location: 'global' + originResponseTimeoutSeconds: 60 + sku: 'Standard_AzureFrontDoor' + customDomains: [ + { + name: 'dep-${namePrefix}-test-${serviceShort}-custom-domain' + hostName: 'dep-${namePrefix}-test-${serviceShort}-custom-domain.azurewebsites.net' + certificateType: 'ManagedCertificate' } - origins: [ - { - name: 'dep-${namePrefix}-test-${serviceShort}-origin' - hostName: 'dep-${namePrefix}-test-${serviceShort}-origin.azurewebsites.net' + ] + origionGroups: [ + { + name: 'dep-${namePrefix}-test-${serviceShort}-origin-group' + loadBalancingSettings: { + additionalLatencyInMilliseconds: 50 + sampleSize: 4 + successfulSamplesRequired: 3 } - ] - } - ] - ruleSets: [ - { - name: 'dep${namePrefix}test${serviceShort}ruleset' - rules: [ - { - name: 'dep${namePrefix}test${serviceShort}rule' - order: 1 - actions: [ - { - name: 'UrlRedirect' - parameters: { - typeName: 'DeliveryRuleUrlRedirectActionParameters' - redirectType: 'PermanentRedirect' - destinationProtocol: 'Https' - customPath: '/test123' - customHostname: 'dev-etradefd.trade.azure.defra.cloud' + origins: [ + { + name: 'dep-${namePrefix}-test-${serviceShort}-origin' + hostName: 'dep-${namePrefix}-test-${serviceShort}-origin.azurewebsites.net' + } + ] + } + ] + ruleSets: [ + { + name: 'dep${namePrefix}test${serviceShort}ruleset' + rules: [ + { + name: 'dep${namePrefix}test${serviceShort}rule' + order: 1 + actions: [ + { + name: 'UrlRedirect' + parameters: { + typeName: 'DeliveryRuleUrlRedirectActionParameters' + redirectType: 'PermanentRedirect' + destinationProtocol: 'Https' + customPath: '/test123' + customHostname: 'dev-etradefd.trade.azure.defra.cloud' + } } - } - ] - } - ] - } - ] - afdEndpoints: [ - { - name: 'dep-${namePrefix}-test-${serviceShort}-afd-endpoint' - routes: [ - { - name: 'dep-${namePrefix}-test-${serviceShort}-afd-route' - originGroupName: 'dep-${namePrefix}-test-${serviceShort}-origin-group' - customDomainName: 'dep-${namePrefix}-test-${serviceShort}-custom-domain' - ruleSets: [ - { - name: 'dep${namePrefix}test${serviceShort}ruleset' - } - ] - } - ] - } - ] + ] + } + ] + } + ] + afdEndpoints: [ + { + name: 'dep-${namePrefix}-test-${serviceShort}-afd-endpoint' + routes: [ + { + name: 'dep-${namePrefix}-test-${serviceShort}-afd-route' + originGroupName: 'dep-${namePrefix}-test-${serviceShort}-origin-group' + customDomainName: 'dep-${namePrefix}-test-${serviceShort}-custom-domain' + ruleSets: [ + { + name: 'dep${namePrefix}test${serviceShort}ruleset' + } + ] + } + ] + } + ] + } } -}] +] diff --git a/avm/res/cdn/profile/tests/e2e/defaults/main.test.bicep b/avm/res/cdn/profile/tests/e2e/defaults/main.test.bicep index 3573faeab4..68c415ae4d 100644 --- a/avm/res/cdn/profile/tests/e2e/defaults/main.test.bicep +++ b/avm/res/cdn/profile/tests/e2e/defaults/main.test.bicep @@ -32,12 +32,14 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - name: 'dep-${namePrefix}-test-${serviceShort}' - location: resourceLocation - sku: 'Standard_Microsoft' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: 'dep-${namePrefix}-test-${serviceShort}' + location: resourceLocation + sku: 'Standard_Microsoft' + } } -}] +] diff --git a/avm/res/cdn/profile/tests/e2e/max/main.test.bicep b/avm/res/cdn/profile/tests/e2e/max/main.test.bicep index 268b935d3b..4a66b858fa 100644 --- a/avm/res/cdn/profile/tests/e2e/max/main.test.bicep +++ b/avm/res/cdn/profile/tests/e2e/max/main.test.bicep @@ -46,64 +46,69 @@ 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: 'dep-${namePrefix}-test-${serviceShort}' - location: resourceLocation - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - originResponseTimeoutSeconds: 60 - sku: 'Standard_Verizon' - endpointProperties: { - originHostHeader: '${nestedDependencies.outputs.storageAccountName}.blob.${environment().suffixes.storage}' - contentTypesToCompress: [ - 'text/plain' - 'text/html' - 'text/css' - 'text/javascript' - 'application/x-javascript' - 'application/javascript' - 'application/json' - 'application/xml' - ] - isCompressionEnabled: true - isHttpAllowed: true - isHttpsAllowed: true - queryStringCachingBehavior: 'IgnoreQueryString' - origins: [ - { - name: 'dep-${namePrefix}-cdn-endpoint01' - properties: { - hostName: '${nestedDependencies.outputs.storageAccountName}.blob.${environment().suffixes.storage}' - httpPort: 80 - httpsPort: 443 - enabled: true +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: 'dep-${namePrefix}-test-${serviceShort}' + location: resourceLocation + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + originResponseTimeoutSeconds: 60 + sku: 'Standard_Verizon' + endpointProperties: { + originHostHeader: '${nestedDependencies.outputs.storageAccountName}.blob.${environment().suffixes.storage}' + contentTypesToCompress: [ + 'text/plain' + 'text/html' + 'text/css' + 'text/javascript' + 'application/x-javascript' + 'application/javascript' + 'application/json' + 'application/xml' + ] + isCompressionEnabled: true + isHttpAllowed: true + isHttpsAllowed: true + queryStringCachingBehavior: 'IgnoreQueryString' + origins: [ + { + name: 'dep-${namePrefix}-cdn-endpoint01' + properties: { + hostName: '${nestedDependencies.outputs.storageAccountName}.blob.${environment().suffixes.storage}' + httpPort: 80 + httpsPort: 443 + enabled: true + } } + ] + originGroups: [] + geoFilters: [] + } + 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' } ] - originGroups: [] - geoFilters: [] } - 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' - } - ] } -}] +] diff --git a/avm/res/cdn/profile/tests/e2e/waf-aligned/main.test.bicep b/avm/res/cdn/profile/tests/e2e/waf-aligned/main.test.bicep index 5cc49fb6c5..7d70c1af4c 100644 --- a/avm/res/cdn/profile/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/cdn/profile/tests/e2e/waf-aligned/main.test.bicep @@ -45,46 +45,48 @@ 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: 'dep-${namePrefix}-test-${serviceShort}' - location: resourceLocation - originResponseTimeoutSeconds: 60 - sku: 'Standard_Verizon' - endpointProperties: { - originHostHeader: '${nestedDependencies.outputs.storageAccountName}.blob.${environment().suffixes.storage}' - contentTypesToCompress: [ - 'text/plain' - 'text/html' - 'text/css' - 'text/javascript' - 'application/x-javascript' - 'application/javascript' - 'application/json' - 'application/xml' - ] - isCompressionEnabled: true - isHttpAllowed: true - isHttpsAllowed: true - queryStringCachingBehavior: 'IgnoreQueryString' - origins: [ - { - name: 'dep-${namePrefix}-cdn-endpoint01' - properties: { - hostName: '${nestedDependencies.outputs.storageAccountName}.blob.${environment().suffixes.storage}' - httpPort: 80 - httpsPort: 443 - enabled: true +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: 'dep-${namePrefix}-test-${serviceShort}' + location: resourceLocation + originResponseTimeoutSeconds: 60 + sku: 'Standard_Verizon' + endpointProperties: { + originHostHeader: '${nestedDependencies.outputs.storageAccountName}.blob.${environment().suffixes.storage}' + contentTypesToCompress: [ + 'text/plain' + 'text/html' + 'text/css' + 'text/javascript' + 'application/x-javascript' + 'application/javascript' + 'application/json' + 'application/xml' + ] + isCompressionEnabled: true + isHttpAllowed: true + isHttpsAllowed: true + queryStringCachingBehavior: 'IgnoreQueryString' + origins: [ + { + name: 'dep-${namePrefix}-cdn-endpoint01' + properties: { + hostName: '${nestedDependencies.outputs.storageAccountName}.blob.${environment().suffixes.storage}' + httpPort: 80 + httpsPort: 443 + enabled: true + } } - } - ] - originGroups: [] - geoFilters: [] + ] + originGroups: [] + geoFilters: [] + } } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/cognitive-services/account/main.bicep b/avm/res/cognitive-services/account/main.bicep index 55a51646ae..b207c3e276 100644 --- a/avm/res/cognitive-services/account/main.bicep +++ b/avm/res/cognitive-services/account/main.bicep @@ -126,75 +126,171 @@ param managedIdentities managedIdentitiesType @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -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 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 builtInRoleNames = { - 'Cognitive Services Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68') - 'Cognitive Services Custom Vision Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c1ff6cc2-c111-46fe-8896-e0ef812ad9f3') - 'Cognitive Services Custom Vision Deployment': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5c4089e1-6d96-4d2f-b296-c1bc7137275f') - 'Cognitive Services Custom Vision Labeler': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '88424f51-ebe7-446f-bc41-7fa16989e96c') - 'Cognitive Services Custom Vision Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '93586559-c37d-4a6b-ba08-b9f0940c2d73') - 'Cognitive Services Custom Vision Trainer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a5ae4ab-0d65-4eeb-be61-29fc9b54394b') - 'Cognitive Services Data Reader (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b59867f0-fa02-499b-be73-45a86b5b3e1c') - 'Cognitive Services Face Recognizer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9894cab4-e18a-44aa-828b-cb588cd6f2d7') - 'Cognitive Services Immersive Reader User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b2de6794-95db-4659-8781-7e080d3f2b9d') - 'Cognitive Services Language Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f07febfe-79bc-46b1-8b37-790e26e6e498') - 'Cognitive Services Language Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7628b7b8-a8b2-4cdc-b46f-e9b35248918e') - 'Cognitive Services Language Writer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f2310ca1-dc64-4889-bb49-c8e0fa3d47a8') - 'Cognitive Services LUIS Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f72c8140-2111-481c-87ff-72b910f6e3f8') - 'Cognitive Services LUIS Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18e81cdc-4e98-4e29-a639-e7d10c5a6226') - 'Cognitive Services LUIS Writer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6322a993-d5c9-4bed-b113-e49bbea25b27') - 'Cognitive Services Metrics Advisor Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cb43c632-a144-4ec5-977c-e80c4affc34a') - 'Cognitive Services Metrics Advisor User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3b20f47b-3825-43cb-8114-4bd2201156a8') - 'Cognitive Services OpenAI Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a001fd3d-188f-4b5d-821b-7da978bf7442') - 'Cognitive Services OpenAI User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd') - 'Cognitive Services QnA Maker Editor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f4cc2bf9-21be-47a1-bdf1-5c5804381025') - 'Cognitive Services QnA Maker Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '466ccd10-b268-4a11-b098-b4849f024126') - 'Cognitive Services Speech Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0e75ca1e-0464-4b4d-8b93-68208a576181') - 'Cognitive Services Speech User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f2dc8367-1007-4938-bd23-fe263f013447') - 'Cognitive Services User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a97b65f3-24c7-4388-baec-2e87135dc908') + 'Cognitive Services Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' + ) + 'Cognitive Services Custom Vision Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'c1ff6cc2-c111-46fe-8896-e0ef812ad9f3' + ) + 'Cognitive Services Custom Vision Deployment': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '5c4089e1-6d96-4d2f-b296-c1bc7137275f' + ) + 'Cognitive Services Custom Vision Labeler': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '88424f51-ebe7-446f-bc41-7fa16989e96c' + ) + 'Cognitive Services Custom Vision Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '93586559-c37d-4a6b-ba08-b9f0940c2d73' + ) + 'Cognitive Services Custom Vision Trainer': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '0a5ae4ab-0d65-4eeb-be61-29fc9b54394b' + ) + 'Cognitive Services Data Reader (Preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b59867f0-fa02-499b-be73-45a86b5b3e1c' + ) + 'Cognitive Services Face Recognizer': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '9894cab4-e18a-44aa-828b-cb588cd6f2d7' + ) + 'Cognitive Services Immersive Reader User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b2de6794-95db-4659-8781-7e080d3f2b9d' + ) + 'Cognitive Services Language Owner': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f07febfe-79bc-46b1-8b37-790e26e6e498' + ) + 'Cognitive Services Language Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '7628b7b8-a8b2-4cdc-b46f-e9b35248918e' + ) + 'Cognitive Services Language Writer': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f2310ca1-dc64-4889-bb49-c8e0fa3d47a8' + ) + 'Cognitive Services LUIS Owner': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f72c8140-2111-481c-87ff-72b910f6e3f8' + ) + 'Cognitive Services LUIS Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18e81cdc-4e98-4e29-a639-e7d10c5a6226' + ) + 'Cognitive Services LUIS Writer': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '6322a993-d5c9-4bed-b113-e49bbea25b27' + ) + 'Cognitive Services Metrics Advisor Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'cb43c632-a144-4ec5-977c-e80c4affc34a' + ) + 'Cognitive Services Metrics Advisor User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '3b20f47b-3825-43cb-8114-4bd2201156a8' + ) + 'Cognitive Services OpenAI Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'a001fd3d-188f-4b5d-821b-7da978bf7442' + ) + 'Cognitive Services OpenAI User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' + ) + 'Cognitive Services QnA Maker Editor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f4cc2bf9-21be-47a1-bdf1-5c5804381025' + ) + 'Cognitive Services QnA Maker Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '466ccd10-b268-4a11-b098-b4849f024126' + ) + 'Cognitive Services Speech Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '0e75ca1e-0464-4b4d-8b93-68208a576181' + ) + 'Cognitive Services Speech User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f2dc8367-1007-4938-bd23-fe263f013447' + ) + 'Cognitive Services User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'a97b65f3-24c7-4388-baec-2e87135dc908' + ) 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.cognitiveservices-account.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.cognitiveservices-account.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} -resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId)) { - name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) - scope: resourceGroup(split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4]) - - resource cMKKey 'keys@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { - name: customerManagedKey.?keyName ?? 'dummyKey' +resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = + if (!empty(customerManagedKey.?keyVaultResourceId)) { + name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) + scope: resourceGroup( + split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], + split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4] + ) + + resource cMKKey 'keys@2023-02-01' existing = + if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { + name: customerManagedKey.?keyName ?? 'dummyKey' + } } -} -resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { - name: last(split(customerManagedKey.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) - scope: resourceGroup(split((customerManagedKey.?userAssignedIdentityResourceId ?? '//'), '/')[2], split((customerManagedKey.?userAssignedIdentityResourceId ?? '////'), '/')[4]) -} +resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = + if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { + name: last(split(customerManagedKey.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) + scope: resourceGroup( + split((customerManagedKey.?userAssignedIdentityResourceId ?? '//'), '/')[2], + split((customerManagedKey.?userAssignedIdentityResourceId ?? '////'), '/')[4] + ) + } resource cognitiveService 'Microsoft.CognitiveServices/accounts@2023-05-01' = { name: name @@ -207,24 +303,34 @@ resource cognitiveService 'Microsoft.CognitiveServices/accounts@2023-05-01' = { } properties: { customSubDomainName: customSubDomainName - networkAcls: !empty(networkAcls ?? {}) ? { - defaultAction: networkAcls.?defaultAction - virtualNetworkRules: networkAcls.?virtualNetworkRules ?? [] - ipRules: networkAcls.?ipRules ?? [] - } : null - publicNetworkAccess: !empty(publicNetworkAccess) ? publicNetworkAccess : (!empty(networkAcls) ? 'Enabled' : 'Disabled') + networkAcls: !empty(networkAcls ?? {}) + ? { + defaultAction: networkAcls.?defaultAction + virtualNetworkRules: networkAcls.?virtualNetworkRules ?? [] + ipRules: networkAcls.?ipRules ?? [] + } + : null + publicNetworkAccess: !empty(publicNetworkAccess) + ? publicNetworkAccess + : (!empty(networkAcls) ? 'Enabled' : 'Disabled') allowedFqdnList: allowedFqdnList apiProperties: apiProperties disableLocalAuth: disableLocalAuth - encryption: !empty(customerManagedKey) ? { - keySource: 'Microsoft.KeyVault' - keyVaultProperties: { - identityClientId: !empty(customerManagedKey.?userAssignedIdentityResourceId ?? '') ? cMKUserAssignedIdentity.properties.clientId : null - keyVaultUri: cMKKeyVault.properties.vaultUri - keyName: customerManagedKey!.keyName - keyVersion: !empty(customerManagedKey.?keyVersion ?? '') ? customerManagedKey!.keyVersion : last(split(cMKKeyVault::cMKKey.properties.keyUriWithVersion, '/')) - } - } : null + encryption: !empty(customerManagedKey) + ? { + keySource: 'Microsoft.KeyVault' + keyVaultProperties: { + identityClientId: !empty(customerManagedKey.?userAssignedIdentityResourceId ?? '') + ? cMKUserAssignedIdentity.properties.clientId + : null + keyVaultUri: cMKKeyVault.properties.vaultUri + keyName: customerManagedKey!.keyName + keyVersion: !empty(customerManagedKey.?keyVersion ?? '') + ? customerManagedKey!.keyVersion + : last(split(cMKKeyVault::cMKKey.properties.keyUriWithVersion, '/')) + } + } + : null migrationToken: migrationToken restore: restore restrictOutboundNetworkAccess: restrictOutboundNetworkAccess @@ -233,93 +339,116 @@ resource cognitiveService 'Microsoft.CognitiveServices/accounts@2023-05-01' = { } } -resource cognitiveService_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.' +resource cognitiveService_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: cognitiveService } - scope: cognitiveService -} -resource cognitiveService_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource cognitiveService_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: cognitiveService } - scope: cognitiveService -}] - -module cognitiveService_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-CognitiveService-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' - privateLinkServiceConnections: [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' - properties: { - privateLinkServiceId: cognitiveService.id - groupIds: [ - privateEndpoint.?service ?? 'account' - ] +] + +module cognitiveService_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-CognitiveService-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' + privateLinkServiceConnections: [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' + properties: { + privateLinkServiceId: cognitiveService.id + groupIds: [ + privateEndpoint.?service ?? 'account' + ] + } } - } - ] - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' - properties: { - privateLinkServiceId: cognitiveService.id - groupIds: [ - privateEndpoint.?service ?? 'account' + ] + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' + properties: { + privateLinkServiceId: cognitiveService.id + groupIds: [ + privateEndpoint.?service ?? 'account' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] +] -resource cognitiveService_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(cognitiveService.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource cognitiveService_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(cognitiveService.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: cognitiveService } - scope: cognitiveService -}] +] @description('The name of the cognitive services account.') output name string = cognitiveService.name diff --git a/avm/res/cognitive-services/account/main.json b/avm/res/cognitive-services/account/main.json index a45302ba9e..6fd6d4050a 100644 --- a/avm/res/cognitive-services/account/main.json +++ b/avm/res/cognitive-services/account/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "6670691272648355802" + "version": "0.26.54.24096", + "templateHash": "4593361593861215330" }, "name": "Cognitive Services", "description": "This module deploys a Cognitive Service.", diff --git a/avm/res/cognitive-services/account/tests/e2e/defaults/main.test.bicep b/avm/res/cognitive-services/account/tests/e2e/defaults/main.test.bicep index 37a7e34a26..2b282ac938 100644 --- a/avm/res/cognitive-services/account/tests/e2e/defaults/main.test.bicep +++ b/avm/res/cognitive-services/account/tests/e2e/defaults/main.test.bicep @@ -36,12 +36,14 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { // ============== // @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' - kind: 'SpeechServices' - location: resourceLocation +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + kind: 'SpeechServices' + location: resourceLocation + } } -}] +] diff --git a/avm/res/cognitive-services/account/tests/e2e/max/main.test.bicep b/avm/res/cognitive-services/account/tests/e2e/max/main.test.bicep index c133cecb59..1ba0cf8985 100644 --- a/avm/res/cognitive-services/account/tests/e2e/max/main.test.bicep +++ b/avm/res/cognitive-services/account/tests/e2e/max/main.test.bicep @@ -59,124 +59,129 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t // 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' - kind: 'Face' - customSubDomainName: '${namePrefix}x${serviceShort}' - location: resourceLocation - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + kind: 'Face' + customSubDomainName: '${namePrefix}x${serviceShort}' + location: resourceLocation + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + logCategoriesAndGroups: [ + { + category: 'RequestResponse' + } + { + category: 'Audit' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + networkAcls: { + defaultAction: 'Deny' + ipRules: [ { - category: 'AllMetrics' + value: '40.74.28.0/23' } ] - logCategoriesAndGroups: [ - { - category: 'RequestResponse' - } + virtualNetworkRules: [ { - category: 'Audit' + id: nestedDependencies.outputs.subnetResourceId + ignoreMissingVnetServiceEndpoint: false } ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - networkAcls: { - defaultAction: 'Deny' - ipRules: [ + publicNetworkAccess: 'Disabled' + roleAssignments: [ { - value: '40.74.28.0/23' + roleDefinitionIdOrName: 'Owner' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' } - ] - virtualNetworkRules: [ { - id: nestedDependencies.outputs.subnetResourceId - ignoreMissingVnetServiceEndpoint: false + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' } - ] - } - publicNetworkAccess: 'Disabled' - 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' - } - ] - sku: 'S0' - managedIdentities: { - systemAssigned: true - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + { + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' } - ipConfigurations: [ - { - name: 'myIPconfig' - properties: { - groupId: 'account' - memberName: 'default' - privateIPAddress: '10.0.0.10' - } - } - ] - customDnsConfigs: [ - { - fqdn: 'abc.account.com' - ipAddresses: [ - '10.0.0.10' - ] - } + ] + sku: 'S0' + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId ] } - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + ipConfigurations: [ + { + name: 'myIPconfig' + properties: { + groupId: 'account' + memberName: 'default' + privateIPAddress: '10.0.0.10' + } + } + ] + customDnsConfigs: [ + { + fqdn: 'abc.account.com' + ipAddresses: [ + '10.0.0.10' + ] + } + ] + } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/cognitive-services/account/tests/e2e/speech/main.test.bicep b/avm/res/cognitive-services/account/tests/e2e/speech/main.test.bicep index d115398bf1..a4c8eb799b 100644 --- a/avm/res/cognitive-services/account/tests/e2e/speech/main.test.bicep +++ b/avm/res/cognitive-services/account/tests/e2e/speech/main.test.bicep @@ -45,41 +45,43 @@ 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' - kind: 'SpeechServices' - location: resourceLocation - customSubDomainName: '${namePrefix}speechdomain' - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + kind: 'SpeechServices' + location: resourceLocation + customSubDomainName: '${namePrefix}speechdomain' + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } - } - ] - sku: 'S0' - managedIdentities: { - systemAssigned: true - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId ] + sku: 'S0' + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/cognitive-services/account/tests/e2e/system-assigned-cmk-encryption/dependencies.bicep b/avm/res/cognitive-services/account/tests/e2e/system-assigned-cmk-encryption/dependencies.bicep index 3fe7da6af3..64f4ad94b8 100644 --- a/avm/res/cognitive-services/account/tests/e2e/system-assigned-cmk-encryption/dependencies.bicep +++ b/avm/res/cognitive-services/account/tests/e2e/system-assigned-cmk-encryption/dependencies.bicep @@ -53,7 +53,10 @@ resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { scope: keyVault::key properties: { principalId: cognitiveService.identity.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '12338af0-0e69-4776-bea7-57ae8d297424' + ) // Key Vault Crypto User principalType: 'ServicePrincipal' } } diff --git a/avm/res/cognitive-services/account/tests/e2e/system-assigned-cmk-encryption/main.test.bicep b/avm/res/cognitive-services/account/tests/e2e/system-assigned-cmk-encryption/main.test.bicep index 3e79483631..b9120e533a 100644 --- a/avm/res/cognitive-services/account/tests/e2e/system-assigned-cmk-encryption/main.test.bicep +++ b/avm/res/cognitive-services/account/tests/e2e/system-assigned-cmk-encryption/main.test.bicep @@ -50,25 +50,27 @@ 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: nestedDependencies.outputs.cognitiveServiceName - kind: 'SpeechServices' - location: resourceLocation - customerManagedKey: { - keyName: nestedDependencies.outputs.keyVaultKeyName - keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - } - publicNetworkAccess: 'Enabled' - sku: 'S0' - managedIdentities: { - systemAssigned: true +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: nestedDependencies.outputs.cognitiveServiceName + kind: 'SpeechServices' + location: resourceLocation + customerManagedKey: { + keyName: nestedDependencies.outputs.keyVaultKeyName + keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + } + publicNetworkAccess: 'Enabled' + sku: 'S0' + managedIdentities: { + systemAssigned: true + } + restrictOutboundNetworkAccess: false } - restrictOutboundNetworkAccess: false + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/cognitive-services/account/tests/e2e/user-assigned-cmk-encryption/dependencies.bicep b/avm/res/cognitive-services/account/tests/e2e/user-assigned-cmk-encryption/dependencies.bicep index 5aefaea511..1ad042356a 100644 --- a/avm/res/cognitive-services/account/tests/e2e/user-assigned-cmk-encryption/dependencies.bicep +++ b/avm/res/cognitive-services/account/tests/e2e/user-assigned-cmk-encryption/dependencies.bicep @@ -43,7 +43,10 @@ resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { scope: keyVault::key properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '12338af0-0e69-4776-bea7-57ae8d297424' + ) // Key Vault Crypto User principalType: 'ServicePrincipal' } } diff --git a/avm/res/cognitive-services/account/tests/e2e/user-assigned-cmk-encryption/main.test.bicep b/avm/res/cognitive-services/account/tests/e2e/user-assigned-cmk-encryption/main.test.bicep index f161025c18..8d4a1ed277 100644 --- a/avm/res/cognitive-services/account/tests/e2e/user-assigned-cmk-encryption/main.test.bicep +++ b/avm/res/cognitive-services/account/tests/e2e/user-assigned-cmk-encryption/main.test.bicep @@ -50,28 +50,30 @@ 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' - kind: 'SpeechServices' - location: resourceLocation - customerManagedKey: { - keyName: nestedDependencies.outputs.keyVaultKeyName - keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - userAssignedIdentityResourceId: nestedDependencies.outputs.managedIdentityResourceId - } - publicNetworkAccess: 'Enabled' - sku: 'S0' - 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' + kind: 'SpeechServices' + location: resourceLocation + customerManagedKey: { + keyName: nestedDependencies.outputs.keyVaultKeyName + keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + userAssignedIdentityResourceId: nestedDependencies.outputs.managedIdentityResourceId + } + publicNetworkAccess: 'Enabled' + sku: 'S0' + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + restrictOutboundNetworkAccess: false } - restrictOutboundNetworkAccess: false + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/cognitive-services/account/tests/e2e/waf-aligned/main.test.bicep b/avm/res/cognitive-services/account/tests/e2e/waf-aligned/main.test.bicep index 362a8ade16..53649ec3f4 100644 --- a/avm/res/cognitive-services/account/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/cognitive-services/account/tests/e2e/waf-aligned/main.test.bicep @@ -59,51 +59,53 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t // 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' - kind: 'Face' - location: resourceLocation - customSubDomainName: '${namePrefix}x${serviceShort}' - diagnosticSettings: [ - { - 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' + kind: 'Face' + location: resourceLocation + customSubDomainName: '${namePrefix}x${serviceShort}' + diagnosticSettings: [ + { + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - sku: 'S0' - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + sku: 'S0' + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + managedIdentities: { + systemAssigned: true } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - managedIdentities: { - systemAssigned: true } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/compute/availability-set/main.bicep b/avm/res/compute/availability-set/main.bicep index 62191c9814..778c4e4048 100644 --- a/avm/res/compute/availability-set/main.bicep +++ b/avm/res/compute/availability-set/main.bicep @@ -36,31 +36,50 @@ 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') - 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') - 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') - 'Virtual Machine Data Access Administrator (preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '66f75aeb-eabe-4b70-9f1e-c350c4c9ad04') - 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') + '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' + ) + 'Virtual Machine Administrator Login': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '1c0163c0-47e6-4577-8991-ea5c82e286e4' + ) + 'Virtual Machine Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '9980e02c-c2be-4d73-94e8-173b1dc7cf3c' + ) + 'Virtual Machine Data Access Administrator (preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '66f75aeb-eabe-4b70-9f1e-c350c4c9ad04' + ) + 'Virtual Machine User Login': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'fb879df8-f326-4884-b1cf-06f3ad86be52' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.compute-availabilityset.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.compute-availabilityset.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource availabilitySet 'Microsoft.Compute/availabilitySets@2023-03-01' = { name: name @@ -69,37 +88,48 @@ resource availabilitySet 'Microsoft.Compute/availabilitySets@2023-03-01' = { properties: { platformFaultDomainCount: platformFaultDomainCount platformUpdateDomainCount: platformUpdateDomainCount - proximityPlacementGroup: !empty(proximityPlacementGroupResourceId) ? { - id: proximityPlacementGroupResourceId - } : null + proximityPlacementGroup: !empty(proximityPlacementGroupResourceId) + ? { + id: proximityPlacementGroupResourceId + } + : null } sku: { name: skuName } } -resource availabilitySet_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.' +resource availabilitySet_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: availabilitySet } - scope: availabilitySet -} -resource availabilitySet_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(availabilitySet.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource availabilitySet_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(availabilitySet.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: availabilitySet } - scope: availabilitySet -}] +] @description('The name of the availability set.') output name string = availabilitySet.name diff --git a/avm/res/compute/availability-set/main.json b/avm/res/compute/availability-set/main.json index 038249ef1f..290131af55 100644 --- a/avm/res/compute/availability-set/main.json +++ b/avm/res/compute/availability-set/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "142072316382977028" + "version": "0.26.54.24096", + "templateHash": "9732921541323544854" }, "name": "Availability Sets", "description": "This module deploys an Availability Set.", diff --git a/avm/res/compute/availability-set/tests/e2e/defaults/main.test.bicep b/avm/res/compute/availability-set/tests/e2e/defaults/main.test.bicep index aca453a803..35b2cca188 100644 --- a/avm/res/compute/availability-set/tests/e2e/defaults/main.test.bicep +++ b/avm/res/compute/availability-set/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 +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 + } } -}] +] diff --git a/avm/res/compute/availability-set/tests/e2e/max/dependencies.bicep b/avm/res/compute/availability-set/tests/e2e/max/dependencies.bicep index 2c78999e90..5ac87aacbb 100644 --- a/avm/res/compute/availability-set/tests/e2e/max/dependencies.bicep +++ b/avm/res/compute/availability-set/tests/e2e/max/dependencies.bicep @@ -8,13 +8,13 @@ param managedIdentityName string param proximityPlacementGroupName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } resource proximityPlacementGroup 'Microsoft.Compute/proximityPlacementGroups@2022-03-01' = { - name: proximityPlacementGroupName - location: location + name: proximityPlacementGroupName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/compute/availability-set/tests/e2e/max/main.test.bicep b/avm/res/compute/availability-set/tests/e2e/max/main.test.bicep index 4ee1160903..bc1a62c7df 100644 --- a/avm/res/compute/availability-set/tests/e2e/max/main.test.bicep +++ b/avm/res/compute/availability-set/tests/e2e/max/main.test.bicep @@ -46,38 +46,43 @@ 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 - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - proximityPlacementGroupResourceId: nestedDependencies.outputs.proximityPlacementGroupResourceId - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +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 + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + proximityPlacementGroupResourceId: nestedDependencies.outputs.proximityPlacementGroupResourceId + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/compute/availability-set/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/compute/availability-set/tests/e2e/waf-aligned/dependencies.bicep index 9233175e2e..db26ceda3e 100644 --- a/avm/res/compute/availability-set/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/compute/availability-set/tests/e2e/waf-aligned/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param proximityPlacementGroupName string resource proximityPlacementGroup 'Microsoft.Compute/proximityPlacementGroups@2022-03-01' = { - name: proximityPlacementGroupName - location: location + name: proximityPlacementGroupName + location: location } @description('The resource ID of the created Proximity Placement Group.') diff --git a/avm/res/compute/availability-set/tests/e2e/waf-aligned/main.test.bicep b/avm/res/compute/availability-set/tests/e2e/waf-aligned/main.test.bicep index a27ce67f2b..3fa0902e06 100644 --- a/avm/res/compute/availability-set/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/compute/availability-set/tests/e2e/waf-aligned/main.test.bicep @@ -45,21 +45,23 @@ 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 - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - proximityPlacementGroupResourceId: nestedDependencies.outputs.proximityPlacementGroupResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +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 + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + proximityPlacementGroupResourceId: nestedDependencies.outputs.proximityPlacementGroupResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } } -}] +] diff --git a/avm/res/compute/disk-encryption-set/main.bicep b/avm/res/compute/disk-encryption-set/main.bicep index 18113c865c..5932efeac2 100644 --- a/avm/res/compute/disk-encryption-set/main.bicep +++ b/avm/res/compute/disk-encryption-set/main.bicep @@ -47,44 +47,73 @@ param tags object? @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -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 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 builtInRoleNames = { - Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Data Operator for Managed Disks': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '959f8984-c045-4866-89c7-12bf9737be2e') - 'Disk Backup Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e5e47e6-65f7-47ef-90b5-e5dd4d455f24') - 'Disk Pool Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60fc6e62-5479-42d4-8bf4-67625fcc2840') - 'Disk Restore Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b50d9833-a0cb-478e-945f-707fcc997c13') - 'Disk Snapshot Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce') + 'Data Operator for Managed Disks': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '959f8984-c045-4866-89c7-12bf9737be2e' + ) + 'Disk Backup Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '3e5e47e6-65f7-47ef-90b5-e5dd4d455f24' + ) + 'Disk Pool Operator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '60fc6e62-5479-42d4-8bf4-67625fcc2840' + ) + 'Disk Restore Operator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b50d9833-a0cb-478e-945f-707fcc997c13' + ) + 'Disk Snapshot Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '7efff54f-a5b4-42b5-a1c5-5411624893ce' + ) 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') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.compute-diskencryptionset.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.compute-diskencryptionset.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource keyVault 'Microsoft.KeyVault/vaults@2021-10-01' existing = { name: last(split(keyVaultResourceId, '/'))! @@ -96,17 +125,19 @@ resource keyVault 'Microsoft.KeyVault/vaults@2021-10-01' existing = { } // Note: This is only enabled for user-assigned identities as the service's system-assigned identity isn't available during its initial deployment -module keyVaultPermissions 'modules/nested_keyVaultPermissions.bicep' = [for (userAssignedIdentityResourceId, index) in (managedIdentities.?userAssignedResourceIds ?? []): { - name: '${uniqueString(deployment().name, location)}-DiskEncrSet-KVPermissions-${index}' - params: { - keyName: keyName - keyVaultResourceId: keyVaultResourceId - userAssignedIdentityResourceId: userAssignedIdentityResourceId - rbacAuthorizationEnabled: keyVault.properties.enableRbacAuthorization - location: location +module keyVaultPermissions 'modules/nested_keyVaultPermissions.bicep' = [ + for (userAssignedIdentityResourceId, index) in (managedIdentities.?userAssignedResourceIds ?? []): { + name: '${uniqueString(deployment().name, location)}-DiskEncrSet-KVPermissions-${index}' + params: { + keyName: keyName + keyVaultResourceId: keyVaultResourceId + userAssignedIdentityResourceId: userAssignedIdentityResourceId + rbacAuthorizationEnabled: keyVault.properties.enableRbacAuthorization + location: location + } + scope: resourceGroup(split(keyVaultResourceId, '/')[2], split(keyVaultResourceId, '/')[4]) } - scope: resourceGroup(split(keyVaultResourceId, '/')[2], split(keyVaultResourceId, '/')[4]) -}] +] resource diskEncryptionSet 'Microsoft.Compute/diskEncryptionSets@2022-07-02' = { name: name @@ -118,7 +149,9 @@ resource diskEncryptionSet 'Microsoft.Compute/diskEncryptionSets@2022-07-02' = { sourceVault: { id: keyVaultResourceId } - keyUrl: !empty(keyVersion) ? '${keyVault::key.properties.keyUri}/${keyVersion}' : keyVault::key.properties.keyUriWithVersion + keyUrl: !empty(keyVersion) + ? '${keyVault::key.properties.keyUri}/${keyVersion}' + : keyVault::key.properties.keyUriWithVersion } encryptionType: encryptionType federatedClientId: federatedClientId @@ -129,28 +162,37 @@ resource diskEncryptionSet 'Microsoft.Compute/diskEncryptionSets@2022-07-02' = { ] } -resource diskEncryptionSet_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(diskEncryptionSet.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource diskEncryptionSet_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(diskEncryptionSet.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: diskEncryptionSet } - scope: diskEncryptionSet -}] - -resource diskEncryptionSet_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.' +] + +resource diskEncryptionSet_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: diskEncryptionSet } - scope: diskEncryptionSet -} @description('The resource ID of the disk encryption set.') output resourceId string = diskEncryptionSet.id diff --git a/avm/res/compute/disk-encryption-set/main.json b/avm/res/compute/disk-encryption-set/main.json index 74797dbc2d..da2764ea80 100644 --- a/avm/res/compute/disk-encryption-set/main.json +++ b/avm/res/compute/disk-encryption-set/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2337982856441594532" + "version": "0.26.54.24096", + "templateHash": "15675582132137222221" }, "name": "Disk Encryption Sets", "description": "This module deploys a Disk Encryption Set. The module will attempt to set permissions on the provided Key Vault for any used user-assigned identity.", @@ -374,8 +374,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4340767234132084239" + "version": "0.26.54.24096", + "templateHash": "11328049361610922964" } }, "parameters": { @@ -462,8 +462,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "9781242464769385318" + "version": "0.26.54.24096", + "templateHash": "3020199531226338329" }, "name": "Key Vault Access Policies", "description": "This module deploys a Key Vault Access Policy.", diff --git a/avm/res/compute/disk-encryption-set/tests/e2e/accessPolicies/dependencies.bicep b/avm/res/compute/disk-encryption-set/tests/e2e/accessPolicies/dependencies.bicep index 2024e8644e..4bc293926f 100644 --- a/avm/res/compute/disk-encryption-set/tests/e2e/accessPolicies/dependencies.bicep +++ b/avm/res/compute/disk-encryption-set/tests/e2e/accessPolicies/dependencies.bicep @@ -8,34 +8,34 @@ param keyVaultName string param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { - name: keyVaultName - location: location - properties: { - sku: { - family: 'A' - name: 'standard' - } - tenantId: tenant().tenantId - enablePurgeProtection: true // Required by disk encryption set - softDeleteRetentionInDays: 7 - enabledForTemplateDeployment: true - enabledForDiskEncryption: true - enabledForDeployment: true - enableRbacAuthorization: false - accessPolicies: [] + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' } - - resource key 'keys@2022-07-01' = { - name: 'keyEncryptionKey' - properties: { - kty: 'RSA' - } + tenantId: tenant().tenantId + enablePurgeProtection: true // Required by disk encryption set + softDeleteRetentionInDays: 7 + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: false + accessPolicies: [] + } + + resource key 'keys@2022-07-01' = { + name: 'keyEncryptionKey' + properties: { + kty: 'RSA' } + } } @description('The resource ID of the created Key Vault.') diff --git a/avm/res/compute/disk-encryption-set/tests/e2e/accessPolicies/main.test.bicep b/avm/res/compute/disk-encryption-set/tests/e2e/accessPolicies/main.test.bicep index af904fb339..5730cc4f3c 100644 --- a/avm/res/compute/disk-encryption-set/tests/e2e/accessPolicies/main.test.bicep +++ b/avm/res/compute/disk-encryption-set/tests/e2e/accessPolicies/main.test.bicep @@ -50,44 +50,49 @@ 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 - keyName: nestedDependencies.outputs.keyName - keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +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 + keyName: nestedDependencies.outputs.keyName + keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + 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' + } + ] + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] } - { - 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' + Role: 'DeploymentValidation' } - ] - managedIdentities: { - systemAssigned: true - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/compute/disk-encryption-set/tests/e2e/defaults/dependencies.bicep b/avm/res/compute/disk-encryption-set/tests/e2e/defaults/dependencies.bicep index 22b4344b68..a79f18bab3 100644 --- a/avm/res/compute/disk-encryption-set/tests/e2e/defaults/dependencies.bicep +++ b/avm/res/compute/disk-encryption-set/tests/e2e/defaults/dependencies.bicep @@ -5,29 +5,29 @@ param location string = resourceGroup().location param keyVaultName string resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { - name: keyVaultName - location: location - properties: { - sku: { - family: 'A' - name: 'standard' - } - tenantId: tenant().tenantId - enablePurgeProtection: true // Required by disk encryption set - softDeleteRetentionInDays: 7 - enabledForTemplateDeployment: true - enabledForDiskEncryption: true - enabledForDeployment: true - enableRbacAuthorization: true - accessPolicies: [] + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' } + tenantId: tenant().tenantId + enablePurgeProtection: true // Required by disk encryption set + softDeleteRetentionInDays: 7 + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } - resource key 'keys@2022-07-01' = { - name: 'keyEncryptionKey' - properties: { - kty: 'RSA' - } + resource key 'keys@2022-07-01' = { + name: 'keyEncryptionKey' + properties: { + kty: 'RSA' } + } } @description('The resource ID of the created Key Vault.') diff --git a/avm/res/compute/disk-encryption-set/tests/e2e/defaults/main.test.bicep b/avm/res/compute/disk-encryption-set/tests/e2e/defaults/main.test.bicep index d8302d5a8b..26d731b9ff 100644 --- a/avm/res/compute/disk-encryption-set/tests/e2e/defaults/main.test.bicep +++ b/avm/res/compute/disk-encryption-set/tests/e2e/defaults/main.test.bicep @@ -49,16 +49,18 @@ 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' - keyName: nestedDependencies.outputs.keyName - keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - location: resourceLocation +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + keyName: nestedDependencies.outputs.keyName + keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + location: resourceLocation + } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/compute/disk-encryption-set/tests/e2e/max/dependencies.bicep b/avm/res/compute/disk-encryption-set/tests/e2e/max/dependencies.bicep index 62321ebe98..e6e79856d7 100644 --- a/avm/res/compute/disk-encryption-set/tests/e2e/max/dependencies.bicep +++ b/avm/res/compute/disk-encryption-set/tests/e2e/max/dependencies.bicep @@ -8,34 +8,34 @@ param keyVaultName string param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { - name: keyVaultName - location: location - properties: { - sku: { - family: 'A' - name: 'standard' - } - tenantId: tenant().tenantId - enablePurgeProtection: true // Required by disk encryption set - softDeleteRetentionInDays: 7 - enabledForTemplateDeployment: true - enabledForDiskEncryption: true - enabledForDeployment: true - enableRbacAuthorization: true - accessPolicies: [] + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' } - - resource key 'keys@2022-07-01' = { - name: 'keyEncryptionKey' - properties: { - kty: 'RSA' - } + tenantId: tenant().tenantId + enablePurgeProtection: true // Required by disk encryption set + softDeleteRetentionInDays: 7 + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } + + resource key 'keys@2022-07-01' = { + name: 'keyEncryptionKey' + properties: { + kty: 'RSA' } + } } @description('The resource ID of the created Key Vault.') diff --git a/avm/res/compute/disk-encryption-set/tests/e2e/max/main.test.bicep b/avm/res/compute/disk-encryption-set/tests/e2e/max/main.test.bicep index 2ad07c7a66..bd27d88592 100644 --- a/avm/res/compute/disk-encryption-set/tests/e2e/max/main.test.bicep +++ b/avm/res/compute/disk-encryption-set/tests/e2e/max/main.test.bicep @@ -50,47 +50,52 @@ 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 - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - keyName: nestedDependencies.outputs.keyName - keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +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 + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + keyName: nestedDependencies.outputs.keyName + keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + 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' + } + ] + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] } - { - 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' + Role: 'DeploymentValidation' } - ] - managedIdentities: { - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/compute/disk-encryption-set/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/compute/disk-encryption-set/tests/e2e/waf-aligned/dependencies.bicep index a893a4e5de..336e29b226 100644 --- a/avm/res/compute/disk-encryption-set/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/compute/disk-encryption-set/tests/e2e/waf-aligned/dependencies.bicep @@ -8,34 +8,34 @@ param keyVaultName string param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { - name: keyVaultName - location: location - properties: { - sku: { - family: 'A' - name: 'standard' - } - tenantId: tenant().tenantId - enablePurgeProtection: true // Required by disk encryption set - softDeleteRetentionInDays: 7 - enabledForTemplateDeployment: true - enabledForDiskEncryption: true - enabledForDeployment: true - enableRbacAuthorization: true - accessPolicies: [] + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' } - - resource key 'keys@2022-07-01' = { - name: 'keyEncryptionKey' - properties: { - kty: 'RSA' - } + tenantId: tenant().tenantId + enablePurgeProtection: true // Required by disk encryption set + softDeleteRetentionInDays: 7 + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } + + resource key 'keys@2022-07-01' = { + name: 'keyEncryptionKey' + properties: { + kty: 'RSA' } + } } @description('The resource ID of the created Key Vault.') diff --git a/avm/res/compute/disk-encryption-set/tests/e2e/waf-aligned/main.test.bicep b/avm/res/compute/disk-encryption-set/tests/e2e/waf-aligned/main.test.bicep index 3c325e9232..d0438eb915 100644 --- a/avm/res/compute/disk-encryption-set/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/compute/disk-encryption-set/tests/e2e/waf-aligned/main.test.bicep @@ -50,26 +50,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 - keyName: nestedDependencies.outputs.keyName - keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - managedIdentities: { - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +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 + keyName: nestedDependencies.outputs.keyName + keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/compute/disk/main.bicep b/avm/res/compute/disk/main.bicep index 00701ce256..a4f07803e8 100644 --- a/avm/res/compute/disk/main.bicep +++ b/avm/res/compute/disk/main.bicep @@ -132,34 +132,56 @@ param enableTelemetry bool = true var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Data Operator for Managed Disks': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '959f8984-c045-4866-89c7-12bf9737be2e') - 'Disk Backup Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e5e47e6-65f7-47ef-90b5-e5dd4d455f24') - 'Disk Pool Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60fc6e62-5479-42d4-8bf4-67625fcc2840') - 'Disk Restore Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b50d9833-a0cb-478e-945f-707fcc997c13') - 'Disk Snapshot Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce') + 'Data Operator for Managed Disks': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '959f8984-c045-4866-89c7-12bf9737be2e' + ) + 'Disk Backup Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '3e5e47e6-65f7-47ef-90b5-e5dd4d455f24' + ) + 'Disk Pool Operator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '60fc6e62-5479-42d4-8bf4-67625fcc2840' + ) + 'Disk Restore Operator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b50d9833-a0cb-478e-945f-707fcc997c13' + ) + 'Disk Snapshot Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '7efff54f-a5b4-42b5-a1c5-5411624893ce' + ) 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') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.compute-disk.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.compute-disk.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource disk 'Microsoft.Compute/disks@2022-07-02' = { name: name @@ -173,9 +195,11 @@ resource disk 'Microsoft.Compute/disks@2022-07-02' = { completionPercent: completionPercent creationData: { createOption: createOption - imageReference: createOption == 'FromImage' ? { - id: imageReferenceId - } : null + imageReference: createOption == 'FromImage' + ? { + id: imageReferenceId + } + : null logicalSectorSize: contains(sku, 'Ultra') ? logicalSectorSize : null securityDataUri: createOption == 'ImportSecure' ? securityDataUri : null sourceResourceId: createOption == 'Copy' ? sourceResourceId : null @@ -192,35 +216,46 @@ resource disk 'Microsoft.Compute/disks@2022-07-02' = { optimizedForFrequentAttach: optimizedForFrequentAttach osType: !empty(osType) ? osType : any(null) publicNetworkAccess: publicNetworkAccess - supportedCapabilities: !empty(osType) ? { - acceleratedNetwork: acceleratedNetwork - architecture: !empty(architecture) ? architecture : null - } : {} + supportedCapabilities: !empty(osType) + ? { + acceleratedNetwork: acceleratedNetwork + architecture: !empty(architecture) ? architecture : null + } + : {} } } -resource disk_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.' +resource disk_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: disk } - scope: disk -} -resource disk_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(disk.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource disk_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(disk.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: disk } - scope: disk -}] +] @description('The resource group the disk was deployed into.') output resourceGroupName string = resourceGroup().name diff --git a/avm/res/compute/disk/main.json b/avm/res/compute/disk/main.json index 7c41b3cc5d..c786f7e240 100644 --- a/avm/res/compute/disk/main.json +++ b/avm/res/compute/disk/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "6226788182357954709" + "version": "0.26.54.24096", + "templateHash": "5405955290856274825" }, "name": "Compute Disks", "description": "This module deploys a Compute Disk", diff --git a/avm/res/compute/disk/tests/e2e/defaults/main.test.bicep b/avm/res/compute/disk/tests/e2e/defaults/main.test.bicep index 97e32b8ad4..1e04040508 100644 --- a/avm/res/compute/disk/tests/e2e/defaults/main.test.bicep +++ b/avm/res/compute/disk/tests/e2e/defaults/main.test.bicep @@ -35,13 +35,15 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { // 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 - sku: 'Standard_LRS' - diskSizeGB: 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 + sku: 'Standard_LRS' + diskSizeGB: 1 + } } -}] +] diff --git a/avm/res/compute/disk/tests/e2e/image/dependencies.bicep b/avm/res/compute/disk/tests/e2e/image/dependencies.bicep index 616cf219fe..2c8183e726 100644 --- a/avm/res/compute/disk/tests/e2e/image/dependencies.bicep +++ b/avm/res/compute/disk/tests/e2e/image/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created managed identity.') diff --git a/avm/res/compute/disk/tests/e2e/image/main.test.bicep b/avm/res/compute/disk/tests/e2e/image/main.test.bicep index 3ebbb0e17d..cd850c0c4f 100644 --- a/avm/res/compute/disk/tests/e2e/image/main.test.bicep +++ b/avm/res/compute/disk/tests/e2e/image/main.test.bicep @@ -44,14 +44,16 @@ module nestedDependencies 'dependencies.bicep' = { // 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 - sku: 'Standard_LRS' - createOption: 'FromImage' - imageReferenceId: '${subscription().id}/Providers/Microsoft.Compute/Locations/westeurope/Publishers/MicrosoftWindowsServer/ArtifactTypes/VMImage/Offers/WindowsServer/Skus/2022-datacenter-azure-edition/Versions/20348.1006.220908' +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 + sku: 'Standard_LRS' + createOption: 'FromImage' + imageReferenceId: '${subscription().id}/Providers/Microsoft.Compute/Locations/westeurope/Publishers/MicrosoftWindowsServer/ArtifactTypes/VMImage/Offers/WindowsServer/Skus/2022-datacenter-azure-edition/Versions/20348.1006.220908' + } } -}] +] diff --git a/avm/res/compute/disk/tests/e2e/import/dependencies.bicep b/avm/res/compute/disk/tests/e2e/import/dependencies.bicep index 038eb6f8ac..3d1a1dac7e 100644 --- a/avm/res/compute/disk/tests/e2e/import/dependencies.bicep +++ b/avm/res/compute/disk/tests/e2e/import/dependencies.bicep @@ -136,7 +136,7 @@ resource copyVhdDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10- cleanupPreference: 'OnSuccess' forceUpdateTag: baseTime } - dependsOn: [ triggerImageDeploymentScript ] + dependsOn: [triggerImageDeploymentScript] } @description('The URI of the created VHD.') diff --git a/avm/res/compute/disk/tests/e2e/import/dependencies_rbac.bicep b/avm/res/compute/disk/tests/e2e/import/dependencies_rbac.bicep index cdca1b63bd..f28142392e 100644 --- a/avm/res/compute/disk/tests/e2e/import/dependencies_rbac.bicep +++ b/avm/res/compute/disk/tests/e2e/import/dependencies_rbac.bicep @@ -9,7 +9,10 @@ param managedIdentityPrincipalId string resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { name: guid(subscription().subscriptionId, 'Contributor', managedIdentityResourceId) properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b24988ac-6180-42a0-ab88-20f7382dd24c' + ) // Contributor principalId: managedIdentityPrincipalId principalType: 'ServicePrincipal' } diff --git a/avm/res/compute/disk/tests/e2e/import/main.test.bicep b/avm/res/compute/disk/tests/e2e/import/main.test.bicep index 66553f7301..6acc81a6dd 100644 --- a/avm/res/compute/disk/tests/e2e/import/main.test.bicep +++ b/avm/res/compute/disk/tests/e2e/import/main.test.bicep @@ -51,15 +51,17 @@ module nestedDependencies 'dependencies.bicep' = { // 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 - sku: 'Standard_LRS' - createOption: 'Import' - sourceUri: nestedDependencies.outputs.vhdUri - storageAccountId: nestedDependencies.outputs.storageAccountResourceId +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 + sku: 'Standard_LRS' + createOption: 'Import' + sourceUri: nestedDependencies.outputs.vhdUri + storageAccountId: nestedDependencies.outputs.storageAccountResourceId + } } -}] +] diff --git a/avm/res/compute/disk/tests/e2e/max/dependencies.bicep b/avm/res/compute/disk/tests/e2e/max/dependencies.bicep index 616cf219fe..2c8183e726 100644 --- a/avm/res/compute/disk/tests/e2e/max/dependencies.bicep +++ b/avm/res/compute/disk/tests/e2e/max/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created managed identity.') diff --git a/avm/res/compute/disk/tests/e2e/max/main.test.bicep b/avm/res/compute/disk/tests/e2e/max/main.test.bicep index 9052419c5e..0bbafb98e5 100644 --- a/avm/res/compute/disk/tests/e2e/max/main.test.bicep +++ b/avm/res/compute/disk/tests/e2e/max/main.test.bicep @@ -44,44 +44,49 @@ module nestedDependencies 'dependencies.bicep' = { // 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 - sku: 'UltraSSD_LRS' - diskIOPSReadWrite: 500 - diskMBpsReadWrite: 60 - diskSizeGB: 128 - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - logicalSectorSize: 512 - osType: 'Windows' - publicNetworkAccess: 'Enabled' - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +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 + sku: 'UltraSSD_LRS' + diskIOPSReadWrite: 500 + diskMBpsReadWrite: 60 + diskSizeGB: 128 + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + logicalSectorSize: 512 + osType: 'Windows' + publicNetworkAccess: 'Enabled' + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/compute/disk/tests/e2e/waf-aligned/main.test.bicep b/avm/res/compute/disk/tests/e2e/waf-aligned/main.test.bicep index d1b92bda7a..b6f4589566 100644 --- a/avm/res/compute/disk/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/compute/disk/tests/e2e/waf-aligned/main.test.bicep @@ -35,27 +35,29 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { // 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 - sku: 'UltraSSD_LRS' - diskIOPSReadWrite: 500 - diskMBpsReadWrite: 60 - diskSizeGB: 128 - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - logicalSectorSize: 512 - osType: 'Windows' - publicNetworkAccess: 'Enabled' - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +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 + sku: 'UltraSSD_LRS' + diskIOPSReadWrite: 500 + diskMBpsReadWrite: 60 + diskSizeGB: 128 + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + logicalSectorSize: 512 + osType: 'Windows' + publicNetworkAccess: 'Enabled' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } } -}] +] diff --git a/avm/res/compute/gallery/application/main.bicep b/avm/res/compute/gallery/application/main.bicep index f0f1ed2a3f..c17ac86830 100644 --- a/avm/res/compute/gallery/application/main.bicep +++ b/avm/res/compute/gallery/application/main.bicep @@ -44,12 +44,21 @@ param tags object? param customActions array? var builtInRoleNames = { - 'Compute Gallery Sharing Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1ef6a3be-d0ac-425d-8c01-acb62866290b') + 'Compute Gallery Sharing Admin': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '1ef6a3be-d0ac-425d-8c01-acb62866290b' + ) 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } resource gallery 'Microsoft.Compute/galleries@2022-03-03' existing = { @@ -72,19 +81,25 @@ resource application 'Microsoft.Compute/galleries/applications@2022-03-03' = { } } -resource application_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(application.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource application_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(application.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: application } - scope: application -}] +] @sys.description('The resource group the image was deployed into.') output resourceGroupName string = resourceGroup().name diff --git a/avm/res/compute/gallery/application/main.json b/avm/res/compute/gallery/application/main.json index c6ccc00385..9c8df87f87 100644 --- a/avm/res/compute/gallery/application/main.json +++ b/avm/res/compute/gallery/application/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "1766982665283226409" + "version": "0.26.54.24096", + "templateHash": "3817884050778525461" }, "name": "Compute Galleries Applications", "description": "This module deploys an Azure Compute Gallery Application.", diff --git a/avm/res/compute/gallery/image/main.bicep b/avm/res/compute/gallery/image/main.bicep index 8c8411fdf0..976535121b 100644 --- a/avm/res/compute/gallery/image/main.bicep +++ b/avm/res/compute/gallery/image/main.bicep @@ -117,12 +117,21 @@ param roleAssignments roleAssignmentType param tags object? var builtInRoleNames = { - 'Compute Gallery Sharing Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1ef6a3be-d0ac-425d-8c01-acb62866290b') + 'Compute Gallery Sharing Admin': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '1ef6a3be-d0ac-425d-8c01-acb62866290b' + ) 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } resource gallery 'Microsoft.Compute/galleries@2022-03-03' existing = { @@ -153,7 +162,8 @@ resource image 'Microsoft.Compute/galleries/images@2022-03-03' = { } } hyperVGeneration: hyperVGeneration ?? (!empty(securityType) ? 'V2' : 'V1') - features: union([ + features: union( + [ { name: 'IsAcceleratedNetworkSupported' value: '${isAcceleratedNetworkSupported}' @@ -163,12 +173,15 @@ resource image 'Microsoft.Compute/galleries/images@2022-03-03' = { value: '${isHibernateSupported}' } ], - (securityType != 'Standard' ? [ - { - name: 'SecurityType' - value: securityType - } - ] : [])) + (securityType != 'Standard' + ? [ + { + name: 'SecurityType' + value: securityType + } + ] + : []) + ) description: description eula: eula privacyStatementUri: privacyStatementUri @@ -185,19 +198,25 @@ resource image 'Microsoft.Compute/galleries/images@2022-03-03' = { } } -resource image_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(image.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource image_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(image.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: image } - scope: image -}] +] @sys.description('The resource group the image was deployed into.') output resourceGroupName string = resourceGroup().name diff --git a/avm/res/compute/gallery/image/main.json b/avm/res/compute/gallery/image/main.json index 8558b28df4..6ff4eedb7d 100644 --- a/avm/res/compute/gallery/image/main.json +++ b/avm/res/compute/gallery/image/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3529471060432554863" + "version": "0.26.54.24096", + "templateHash": "15034895982698413313" }, "name": "Compute Galleries Image Definitions", "description": "This module deploys an Azure Compute Gallery Image Definition.", diff --git a/avm/res/compute/gallery/main.bicep b/avm/res/compute/gallery/main.bicep index bd2d9e7ddd..58b61a145b 100644 --- a/avm/res/compute/gallery/main.bicep +++ b/avm/res/compute/gallery/main.bicep @@ -37,31 +37,41 @@ param sharingProfile object? param softDeletePolicy object? var builtInRoleNames = { - 'Compute Gallery Sharing Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1ef6a3be-d0ac-425d-8c01-acb62866290b') + 'Compute Gallery Sharing Admin': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '1ef6a3be-d0ac-425d-8c01-acb62866290b' + ) 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.compute-gallery.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.compute-gallery.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource gallery 'Microsoft.Compute/galleries@2022-03-03' = { name: name @@ -75,78 +85,91 @@ resource gallery 'Microsoft.Compute/galleries@2022-03-03' = { } } -resource gallery_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.' +resource gallery_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: gallery } - scope: gallery -} -resource gallery_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(gallery.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource gallery_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(gallery.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: gallery } - scope: gallery -}] - -module galleries_applications 'application/main.bicep' = [for (application, index) in (applications ?? []): { - name: '${uniqueString(deployment().name, location)}-Gallery-Application-${index}' - params: { - location: location - name: application.name - galleryName: gallery.name - supportedOSType: application.supportedOSType - description: application.?description - eula: application.?eula - privacyStatementUri: application.?privacyStatementUri - releaseNoteUri: application.?releaseNoteUri - endOfLifeDate: application.?endOfLifeDate - roleAssignments: application.?roleAssignments - customActions: application.?customActions - tags: application.?tags ?? tags +] + +module galleries_applications 'application/main.bicep' = [ + for (application, index) in (applications ?? []): { + name: '${uniqueString(deployment().name, location)}-Gallery-Application-${index}' + params: { + location: location + name: application.name + galleryName: gallery.name + supportedOSType: application.supportedOSType + description: application.?description + eula: application.?eula + privacyStatementUri: application.?privacyStatementUri + releaseNoteUri: application.?releaseNoteUri + endOfLifeDate: application.?endOfLifeDate + roleAssignments: application.?roleAssignments + customActions: application.?customActions + tags: application.?tags ?? tags + } } -}] - -module galleries_images 'image/main.bicep' = [for (image, index) in (images ?? []): { - name: '${uniqueString(deployment().name, location)}-Gallery-Image-${index}' - params: { - location: location - name: image.name - galleryName: gallery.name - osType: image.osType - osState: image.?osState - publisher: image.publisher - offer: image.offer - sku: image.sku - minRecommendedvCPUs: image.?minRecommendedvCPUs - maxRecommendedvCPUs: image.?maxRecommendedvCPUs - minRecommendedMemory: image.?minRecommendedMemory - maxRecommendedMemory: image.?maxRecommendedMemory - hyperVGeneration: image.?hyperVGeneration - securityType: image.?securityType - isAcceleratedNetworkSupported: image.?isAcceleratedNetworkSupported - description: image.?description - eula: image.?eula - privacyStatementUri: image.?privacyStatementUri - releaseNoteUri: image.?releaseNoteUri - productName: image.?productName - planName: image.?planName - planPublisherName: image.?planPublisherName - endOfLife: image.?endOfLife - excludedDiskTypes: image.?excludedDiskTypes - roleAssignments: image.?roleAssignments - tags: image.?tags ?? tags +] + +module galleries_images 'image/main.bicep' = [ + for (image, index) in (images ?? []): { + name: '${uniqueString(deployment().name, location)}-Gallery-Image-${index}' + params: { + location: location + name: image.name + galleryName: gallery.name + osType: image.osType + osState: image.?osState + publisher: image.publisher + offer: image.offer + sku: image.sku + minRecommendedvCPUs: image.?minRecommendedvCPUs + maxRecommendedvCPUs: image.?maxRecommendedvCPUs + minRecommendedMemory: image.?minRecommendedMemory + maxRecommendedMemory: image.?maxRecommendedMemory + hyperVGeneration: image.?hyperVGeneration + securityType: image.?securityType + isAcceleratedNetworkSupported: image.?isAcceleratedNetworkSupported + description: image.?description + eula: image.?eula + privacyStatementUri: image.?privacyStatementUri + releaseNoteUri: image.?releaseNoteUri + productName: image.?productName + planName: image.?planName + planPublisherName: image.?planPublisherName + endOfLife: image.?endOfLife + excludedDiskTypes: image.?excludedDiskTypes + roleAssignments: image.?roleAssignments + tags: image.?tags ?? tags + } } -}] +] @sys.description('The resource ID of the deployed image gallery.') output resourceId string = gallery.id diff --git a/avm/res/compute/gallery/main.json b/avm/res/compute/gallery/main.json index cebcd05b97..c2863f574c 100644 --- a/avm/res/compute/gallery/main.json +++ b/avm/res/compute/gallery/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "7407411978239812730" + "version": "0.26.54.24096", + "templateHash": "5329218260776835511" }, "name": "Azure Compute Galleries", "description": "This module deploys an Azure Compute Gallery (formerly known as Shared Image Gallery).", @@ -319,8 +319,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "1766982665283226409" + "version": "0.26.54.24096", + "templateHash": "3817884050778525461" }, "name": "Compute Galleries Applications", "description": "This module deploys an Azure Compute Gallery Application.", @@ -676,8 +676,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3529471060432554863" + "version": "0.26.54.24096", + "templateHash": "15034895982698413313" }, "name": "Compute Galleries Image Definitions", "description": "This module deploys an Azure Compute Gallery Image Definition.", diff --git a/avm/res/compute/gallery/tests/e2e/defaults/main.test.bicep b/avm/res/compute/gallery/tests/e2e/defaults/main.test.bicep index 56716b94c4..e4e7235dca 100644 --- a/avm/res/compute/gallery/tests/e2e/defaults/main.test.bicep +++ b/avm/res/compute/gallery/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 +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 + } } -}] +] diff --git a/avm/res/compute/gallery/tests/e2e/max/dependencies.bicep b/avm/res/compute/gallery/tests/e2e/max/dependencies.bicep index a7f42aee7b..7be39e253a 100644 --- a/avm/res/compute/gallery/tests/e2e/max/dependencies.bicep +++ b/avm/res/compute/gallery/tests/e2e/max/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/compute/gallery/tests/e2e/max/main.test.bicep b/avm/res/compute/gallery/tests/e2e/max/main.test.bicep index 4fc0d88218..d00744b531 100644 --- a/avm/res/compute/gallery/tests/e2e/max/main.test.bicep +++ b/avm/res/compute/gallery/tests/e2e/max/main.test.bicep @@ -45,130 +45,135 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - applications: [ - { - name: '${namePrefix}-${serviceShort}-appd-001' - supportedOSType: 'Linux' - } - { - name: '${namePrefix}-${serviceShort}-appd-002' - supportedOSType: 'Windows' - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - ] - } - ] - images: [ - { - hyperVGeneration: 'V1' - name: '${namePrefix}-az-imgd-ws-001' - offer: 'WindowsServer' - osType: 'Windows' - publisher: 'MicrosoftWindowsServer' - sku: '2022-datacenter-azure-edition' - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - ] - } - { - hyperVGeneration: 'V2' - isHibernateSupported: true - isAcceleratedNetworkSupported: false - maxRecommendedMemory: 16 - maxRecommendedvCPUs: 8 - minRecommendedMemory: 4 - minRecommendedvCPUs: 2 - name: '${namePrefix}-az-imgd-ws-002' - offer: 'WindowsServer' - osState: 'Generalized' - osType: 'Windows' - publisher: 'MicrosoftWindowsServer' - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - ] - sku: '2022-datacenter-azure-edition-hibernate' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - hyperVGeneration: 'V2' - securityType: 'TrustedLaunch' - maxRecommendedMemory: 16 - maxRecommendedvCPUs: 4 - minRecommendedMemory: 4 - minRecommendedvCPUs: 2 - name: '${namePrefix}-az-imgd-wdtl-001' - offer: 'WindowsDesktop' - osState: 'Generalized' - osType: 'Windows' - publisher: 'MicrosoftWindowsDesktop' - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - ] - sku: 'Win11-21H2' + applications: [ + { + name: '${namePrefix}-${serviceShort}-appd-001' + supportedOSType: 'Linux' + } + { + name: '${namePrefix}-${serviceShort}-appd-002' + supportedOSType: 'Windows' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + } + ] + images: [ + { + hyperVGeneration: 'V1' + name: '${namePrefix}-az-imgd-ws-001' + offer: 'WindowsServer' + osType: 'Windows' + publisher: 'MicrosoftWindowsServer' + sku: '2022-datacenter-azure-edition' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + } + { + hyperVGeneration: 'V2' + isHibernateSupported: true + isAcceleratedNetworkSupported: false + maxRecommendedMemory: 16 + maxRecommendedvCPUs: 8 + minRecommendedMemory: 4 + minRecommendedvCPUs: 2 + name: '${namePrefix}-az-imgd-ws-002' + offer: 'WindowsServer' + osState: 'Generalized' + osType: 'Windows' + publisher: 'MicrosoftWindowsServer' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + sku: '2022-datacenter-azure-edition-hibernate' + } + { + hyperVGeneration: 'V2' + securityType: 'TrustedLaunch' + maxRecommendedMemory: 16 + maxRecommendedvCPUs: 4 + minRecommendedMemory: 4 + minRecommendedvCPUs: 2 + name: '${namePrefix}-az-imgd-wdtl-001' + offer: 'WindowsDesktop' + osState: 'Generalized' + osType: 'Windows' + publisher: 'MicrosoftWindowsDesktop' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + sku: 'Win11-21H2' + } + { + hyperVGeneration: 'V2' + maxRecommendedMemory: 32 + maxRecommendedvCPUs: 4 + minRecommendedMemory: 4 + minRecommendedvCPUs: 1 + name: '${namePrefix}-az-imgd-us-001' + offer: '0001-com-ubuntu-server-focal' + osState: 'Generalized' + osType: 'Linux' + publisher: 'canonical' + sku: '20_04-lts-gen2' + } + ] + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - { - hyperVGeneration: 'V2' - maxRecommendedMemory: 32 - maxRecommendedvCPUs: 4 - minRecommendedMemory: 4 - minRecommendedvCPUs: 1 - name: '${namePrefix}-az-imgd-us-001' - offer: '0001-com-ubuntu-server-focal' - osState: 'Generalized' - osType: 'Linux' - publisher: 'canonical' - sku: '20_04-lts-gen2' - } - ] - 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' - } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/compute/gallery/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/compute/gallery/tests/e2e/waf-aligned/dependencies.bicep index a7f42aee7b..7be39e253a 100644 --- a/avm/res/compute/gallery/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/compute/gallery/tests/e2e/waf-aligned/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/compute/gallery/tests/e2e/waf-aligned/main.test.bicep b/avm/res/compute/gallery/tests/e2e/waf-aligned/main.test.bicep index e31da2c17f..ca7ee02323 100644 --- a/avm/res/compute/gallery/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/compute/gallery/tests/e2e/waf-aligned/main.test.bicep @@ -36,31 +36,33 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - applications: [ - { - name: '${namePrefix}-${serviceShort}-appd-001' - supportedOSType: 'Windows' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + applications: [ + { + name: '${namePrefix}-${serviceShort}-appd-001' + supportedOSType: 'Windows' + } + ] + images: [ + { + name: '${namePrefix}-az-imgd-ws-001' + offer: 'WindowsServer' + osType: 'Windows' + publisher: 'MicrosoftWindowsServer' + sku: '2022-datacenter-azure-edition' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - images: [ - { - name: '${namePrefix}-az-imgd-ws-001' - offer: 'WindowsServer' - osType: 'Windows' - publisher: 'MicrosoftWindowsServer' - sku: '2022-datacenter-azure-edition' - } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/compute/image/main.bicep b/avm/res/compute/image/main.bicep index 4498d30df6..d094eaa081 100644 --- a/avm/res/compute/image/main.bicep +++ b/avm/res/compute/image/main.bicep @@ -67,27 +67,34 @@ 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.compute-image.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.compute-image.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource image 'Microsoft.Compute/images@2022-11-01' = { name: name @@ -102,40 +109,54 @@ resource image 'Microsoft.Compute/images@2022-11-01' = { caching: osDiskCaching storageAccountType: osAccountType osState: osState - diskEncryptionSet: !empty(diskEncryptionSetResourceId) ? { - id: diskEncryptionSetResourceId - } : null + diskEncryptionSet: !empty(diskEncryptionSetResourceId) + ? { + id: diskEncryptionSetResourceId + } + : null diskSizeGB: diskSizeGB - managedDisk: !empty(managedDiskResourceId) ? { - id: managedDiskResourceId - } : null - snapshot: !empty(snapshotResourceId) ? { - id: snapshotResourceId - } : null + managedDisk: !empty(managedDiskResourceId) + ? { + id: managedDiskResourceId + } + : null + snapshot: !empty(snapshotResourceId) + ? { + id: snapshotResourceId + } + : null } dataDisks: dataDisks zoneResilient: zoneResilient } hyperVGeneration: hyperVGeneration - sourceVirtualMachine: !empty(sourceVirtualMachineResourceId) ? { - id: sourceVirtualMachineResourceId - } : null + sourceVirtualMachine: !empty(sourceVirtualMachineResourceId) + ? { + id: sourceVirtualMachineResourceId + } + : null } } -resource image_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(image.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource image_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(image.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: image } - scope: image -}] +] @description('The resource ID of the image.') output resourceId string = image.id diff --git a/avm/res/compute/image/main.json b/avm/res/compute/image/main.json index 3ce18d1b64..0b5e128f2f 100644 --- a/avm/res/compute/image/main.json +++ b/avm/res/compute/image/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "262853591906300834" + "version": "0.26.54.24096", + "templateHash": "7672407789517238611" }, "name": "Images", "description": "This module deploys a Compute Image.", diff --git a/avm/res/compute/image/tests/e2e/defaults/dependencies.bicep b/avm/res/compute/image/tests/e2e/defaults/dependencies.bicep index 7614a52892..fb10204820 100644 --- a/avm/res/compute/image/tests/e2e/defaults/dependencies.bicep +++ b/avm/res/compute/image/tests/e2e/defaults/dependencies.bicep @@ -137,7 +137,7 @@ resource copyVhdDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10- cleanupPreference: 'OnSuccess' forceUpdateTag: baseTime } - dependsOn: [ triggerImageDeploymentScript ] + dependsOn: [triggerImageDeploymentScript] } @description('The URI of the created VHD.') diff --git a/avm/res/compute/image/tests/e2e/defaults/dependencies_rbac.bicep b/avm/res/compute/image/tests/e2e/defaults/dependencies_rbac.bicep index cdca1b63bd..f28142392e 100644 --- a/avm/res/compute/image/tests/e2e/defaults/dependencies_rbac.bicep +++ b/avm/res/compute/image/tests/e2e/defaults/dependencies_rbac.bicep @@ -9,7 +9,10 @@ param managedIdentityPrincipalId string resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { name: guid(subscription().subscriptionId, 'Contributor', managedIdentityResourceId) properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b24988ac-6180-42a0-ab88-20f7382dd24c' + ) // Contributor principalId: managedIdentityPrincipalId principalType: 'ServicePrincipal' } diff --git a/avm/res/compute/image/tests/e2e/defaults/main.test.bicep b/avm/res/compute/image/tests/e2e/defaults/main.test.bicep index 00f8c5b612..1bdd354168 100644 --- a/avm/res/compute/image/tests/e2e/defaults/main.test.bicep +++ b/avm/res/compute/image/tests/e2e/defaults/main.test.bicep @@ -54,15 +54,17 @@ 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 - osAccountType: 'Standard_LRS' - osDiskBlobUri: nestedDependencies.outputs.vhdUri - osDiskCaching: 'ReadWrite' - osType: 'Windows' +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 + osAccountType: 'Standard_LRS' + osDiskBlobUri: nestedDependencies.outputs.vhdUri + osDiskCaching: 'ReadWrite' + osType: 'Windows' + } } -}] +] diff --git a/avm/res/compute/image/tests/e2e/max/dependencies.bicep b/avm/res/compute/image/tests/e2e/max/dependencies.bicep index b37c3cf39f..6a26edc6cf 100644 --- a/avm/res/compute/image/tests/e2e/max/dependencies.bicep +++ b/avm/res/compute/image/tests/e2e/max/dependencies.bicep @@ -143,7 +143,7 @@ resource copyVhdDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10- cleanupPreference: 'OnSuccess' forceUpdateTag: baseTime } - dependsOn: [ triggerImageDeploymentScript ] + dependsOn: [triggerImageDeploymentScript] } resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { @@ -177,7 +177,10 @@ resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { scope: keyVault::key properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '12338af0-0e69-4776-bea7-57ae8d297424' + ) // Key Vault Crypto User principalType: 'ServicePrincipal' } } diff --git a/avm/res/compute/image/tests/e2e/max/dependencies_rbac.bicep b/avm/res/compute/image/tests/e2e/max/dependencies_rbac.bicep index cdca1b63bd..f28142392e 100644 --- a/avm/res/compute/image/tests/e2e/max/dependencies_rbac.bicep +++ b/avm/res/compute/image/tests/e2e/max/dependencies_rbac.bicep @@ -9,7 +9,10 @@ param managedIdentityPrincipalId string resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { name: guid(subscription().subscriptionId, 'Contributor', managedIdentityResourceId) properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b24988ac-6180-42a0-ab88-20f7382dd24c' + ) // Contributor principalId: managedIdentityPrincipalId principalType: 'ServicePrincipal' } diff --git a/avm/res/compute/image/tests/e2e/max/main.test.bicep b/avm/res/compute/image/tests/e2e/max/main.test.bicep index a5d2fb7516..2c88a950cd 100644 --- a/avm/res/compute/image/tests/e2e/max/main.test.bicep +++ b/avm/res/compute/image/tests/e2e/max/main.test.bicep @@ -54,42 +54,47 @@ module nestedDependencies 'dependencies.bicep' = { // 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 - osAccountType: 'Premium_LRS' - osDiskBlobUri: nestedDependencies.outputs.vhdUri - osDiskCaching: 'ReadWrite' - osType: 'Windows' - hyperVGeneration: 'V1' - 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' +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 + osAccountType: 'Premium_LRS' + osDiskBlobUri: nestedDependencies.outputs.vhdUri + osDiskCaching: 'ReadWrite' + osType: 'Windows' + hyperVGeneration: 'V1' + 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' + } + ] + zoneResilient: true + diskEncryptionSetResourceId: nestedDependencies.outputs.diskEncryptionSetResourceId + osState: 'Generalized' + diskSizeGB: 128 + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - zoneResilient: true - diskEncryptionSetResourceId: nestedDependencies.outputs.diskEncryptionSetResourceId - osState: 'Generalized' - diskSizeGB: 128 - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/compute/image/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/compute/image/tests/e2e/waf-aligned/dependencies.bicep index b37c3cf39f..6a26edc6cf 100644 --- a/avm/res/compute/image/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/compute/image/tests/e2e/waf-aligned/dependencies.bicep @@ -143,7 +143,7 @@ resource copyVhdDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10- cleanupPreference: 'OnSuccess' forceUpdateTag: baseTime } - dependsOn: [ triggerImageDeploymentScript ] + dependsOn: [triggerImageDeploymentScript] } resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { @@ -177,7 +177,10 @@ resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { scope: keyVault::key properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '12338af0-0e69-4776-bea7-57ae8d297424' + ) // Key Vault Crypto User principalType: 'ServicePrincipal' } } diff --git a/avm/res/compute/image/tests/e2e/waf-aligned/dependencies_rbac.bicep b/avm/res/compute/image/tests/e2e/waf-aligned/dependencies_rbac.bicep index cdca1b63bd..f28142392e 100644 --- a/avm/res/compute/image/tests/e2e/waf-aligned/dependencies_rbac.bicep +++ b/avm/res/compute/image/tests/e2e/waf-aligned/dependencies_rbac.bicep @@ -9,7 +9,10 @@ param managedIdentityPrincipalId string resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { name: guid(subscription().subscriptionId, 'Contributor', managedIdentityResourceId) properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b24988ac-6180-42a0-ab88-20f7382dd24c' + ) // Contributor principalId: managedIdentityPrincipalId principalType: 'ServicePrincipal' } diff --git a/avm/res/compute/image/tests/e2e/waf-aligned/main.test.bicep b/avm/res/compute/image/tests/e2e/waf-aligned/main.test.bicep index ca784f4643..c4d8bed406 100644 --- a/avm/res/compute/image/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/compute/image/tests/e2e/waf-aligned/main.test.bicep @@ -54,25 +54,27 @@ module nestedDependencies 'dependencies.bicep' = { // 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 - osAccountType: 'Premium_LRS' - osDiskBlobUri: nestedDependencies.outputs.vhdUri - osDiskCaching: 'ReadWrite' - osType: 'Windows' - hyperVGeneration: 'V1' - zoneResilient: true - diskEncryptionSetResourceId: nestedDependencies.outputs.diskEncryptionSetResourceId - osState: 'Generalized' - diskSizeGB: 128 - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +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 + osAccountType: 'Premium_LRS' + osDiskBlobUri: nestedDependencies.outputs.vhdUri + osDiskCaching: 'ReadWrite' + osType: 'Windows' + hyperVGeneration: 'V1' + zoneResilient: true + diskEncryptionSetResourceId: nestedDependencies.outputs.diskEncryptionSetResourceId + osState: 'Generalized' + diskSizeGB: 128 + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } } -}] +] diff --git a/avm/res/compute/proximity-placement-group/main.bicep b/avm/res/compute/proximity-placement-group/main.bicep index e7f657084b..f0a723246d 100644 --- a/avm/res/compute/proximity-placement-group/main.bicep +++ b/avm/res/compute/proximity-placement-group/main.bicep @@ -40,27 +40,34 @@ 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.compute-proximityplacementgroup.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.compute-proximityplacementgroup.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource proximityPlacementGroup 'Microsoft.Compute/proximityPlacementGroups@2022-08-01' = { name: name @@ -74,28 +81,37 @@ resource proximityPlacementGroup 'Microsoft.Compute/proximityPlacementGroups@202 } } -resource proximityPlacementGroup_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.' +resource proximityPlacementGroup_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: proximityPlacementGroup } - scope: proximityPlacementGroup -} -resource proximityPlacementGroup_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(proximityPlacementGroup.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource proximityPlacementGroup_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(proximityPlacementGroup.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: proximityPlacementGroup } - scope: proximityPlacementGroup -}] +] @description('The name of the proximity placement group.') output name string = proximityPlacementGroup.name diff --git a/avm/res/compute/proximity-placement-group/main.json b/avm/res/compute/proximity-placement-group/main.json index 779f0be773..20a1e3cf90 100644 --- a/avm/res/compute/proximity-placement-group/main.json +++ b/avm/res/compute/proximity-placement-group/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2998974371512711861" + "version": "0.26.54.24096", + "templateHash": "10197969165198837306" }, "name": "Proximity Placement Groups", "description": "This module deploys a Proximity Placement Group.", diff --git a/avm/res/compute/proximity-placement-group/tests/e2e/defaults/main.test.bicep b/avm/res/compute/proximity-placement-group/tests/e2e/defaults/main.test.bicep index 4ec0e48342..31714c6f06 100644 --- a/avm/res/compute/proximity-placement-group/tests/e2e/defaults/main.test.bicep +++ b/avm/res/compute/proximity-placement-group/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 +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 + } } -}] +] diff --git a/avm/res/compute/proximity-placement-group/tests/e2e/max/dependencies.bicep b/avm/res/compute/proximity-placement-group/tests/e2e/max/dependencies.bicep index a7f42aee7b..7be39e253a 100644 --- a/avm/res/compute/proximity-placement-group/tests/e2e/max/dependencies.bicep +++ b/avm/res/compute/proximity-placement-group/tests/e2e/max/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/compute/proximity-placement-group/tests/e2e/max/main.test.bicep b/avm/res/compute/proximity-placement-group/tests/e2e/max/main.test.bicep index 71760632e6..f8225519b8 100644 --- a/avm/res/compute/proximity-placement-group/tests/e2e/max/main.test.bicep +++ b/avm/res/compute/proximity-placement-group/tests/e2e/max/main.test.bicep @@ -45,53 +45,58 @@ 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 - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +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 + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + 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' + } + ] + zones: [ + '1' + ] + type: 'Standard' + tags: { + 'hidden-title': 'This is visible in the resource name' + TagA: 'Would you kindly...' + TagB: 'Tags for sale' } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + colocationStatus: { + code: 'ColocationStatus/Aligned' + displayStatus: 'Aligned' + level: 'Info' + message: 'I\'m a default error message' } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + intent: { + vmSizes: [ + 'Standard_B1ms' + 'Standard_B4ms' + ] } - ] - zones: [ - '1' - ] - type: 'Standard' - tags: { - 'hidden-title': 'This is visible in the resource name' - TagA: 'Would you kindly...' - TagB: 'Tags for sale' - } - colocationStatus: { - code: 'ColocationStatus/Aligned' - displayStatus: 'Aligned' - level: 'Info' - message: 'I\'m a default error message' - } - intent: { - vmSizes: [ - 'Standard_B1ms' - 'Standard_B4ms' - ] } } -}] +] diff --git a/avm/res/compute/proximity-placement-group/tests/e2e/waf-aligned/main.test.bicep b/avm/res/compute/proximity-placement-group/tests/e2e/waf-aligned/main.test.bicep index 38aece098e..b98da12996 100644 --- a/avm/res/compute/proximity-placement-group/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/compute/proximity-placement-group/tests/e2e/waf-aligned/main.test.bicep @@ -36,32 +36,34 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 - zones: [ - '1' - ] - type: 'Standard' - tags: { - 'hidden-title': 'This is visible in the resource name' - TagA: 'Would you kindly...' - TagB: 'Tags for sale' - } - colocationStatus: { - code: 'ColocationStatus/Aligned' - displayStatus: 'Aligned' - level: 'Info' - message: 'I\'m a default error message' - } - intent: { - vmSizes: [ - 'Standard_B1ms' - 'Standard_B4ms' +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 + zones: [ + '1' ] + type: 'Standard' + tags: { + 'hidden-title': 'This is visible in the resource name' + TagA: 'Would you kindly...' + TagB: 'Tags for sale' + } + colocationStatus: { + code: 'ColocationStatus/Aligned' + displayStatus: 'Aligned' + level: 'Info' + message: 'I\'m a default error message' + } + intent: { + vmSizes: [ + 'Standard_B1ms' + 'Standard_B4ms' + ] + } } } -}] +] diff --git a/avm/res/compute/ssh-public-key/main.bicep b/avm/res/compute/ssh-public-key/main.bicep index 19204bf4e6..0225692160 100644 --- a/avm/res/compute/ssh-public-key/main.bicep +++ b/avm/res/compute/ssh-public-key/main.bicep @@ -30,27 +30,34 @@ 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.compute-sshpublickey.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.compute-sshpublickey.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource sshPublicKey 'Microsoft.Compute/sshPublicKeys@2023-07-01' = { name: name @@ -61,28 +68,37 @@ resource sshPublicKey 'Microsoft.Compute/sshPublicKeys@2023-07-01' = { } } -resource sshPublicKeyLock '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.' +resource sshPublicKeyLock '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: sshPublicKey } - scope: sshPublicKey -} -resource sshPublicKeyRoleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(sshPublicKey.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource sshPublicKeyRoleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(sshPublicKey.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: sshPublicKey } - scope: sshPublicKey -}] +] @description('The name of the Resource Group the Public SSH Key was created in.') output resourceGroupName string = resourceGroup().name diff --git a/avm/res/compute/ssh-public-key/main.json b/avm/res/compute/ssh-public-key/main.json index b33a3e997c..9c4e8ac8b6 100644 --- a/avm/res/compute/ssh-public-key/main.json +++ b/avm/res/compute/ssh-public-key/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "8813930198344883772" + "version": "0.26.54.24096", + "templateHash": "10976156692729855046" }, "name": "Public SSH Keys", "description": "This module deploys a Public SSH Key.\n\n> Note: The resource does not auto-generate the key for you.", diff --git a/avm/res/compute/ssh-public-key/tests/e2e/max/dependencies.bicep b/avm/res/compute/ssh-public-key/tests/e2e/max/dependencies.bicep index 3665ddc00e..24bbd4da01 100644 --- a/avm/res/compute/ssh-public-key/tests/e2e/max/dependencies.bicep +++ b/avm/res/compute/ssh-public-key/tests/e2e/max/dependencies.bicep @@ -14,41 +14,44 @@ param sshKeyName string param utcValue string = utcNow() resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } // required for the deployment script to create a new temporary ssh public key object resource msi_ContributorRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(resourceGroup().id, 'ManagedIdentityContributor', '#_namePrefix_#') - properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor - principalId: managedIdentity.properties.principalId - principalType: 'ServicePrincipal' - } + name: guid(resourceGroup().id, 'ManagedIdentityContributor', '#_namePrefix_#') + properties: { + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b24988ac-6180-42a0-ab88-20f7382dd24c' + ) // Contributor + principalId: managedIdentity.properties.principalId + principalType: 'ServicePrincipal' + } } resource createPubKeyScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { - name: generateSshPubKeyScriptName - location: location - kind: 'AzurePowerShell' - identity: { - type: 'UserAssigned' - userAssignedIdentities: { - '${managedIdentity.id}': {} - } - } - properties: { - azPowerShellVersion: '8.0' - retentionInterval: 'P1D' - arguments: '-ResourceGroupName ${resourceGroup().name} -SSHKeyName ${sshKeyName}' - scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/New-SSHKey.ps1') - cleanupPreference: 'OnExpiration' - forceUpdateTag: utcValue + name: generateSshPubKeyScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} } - dependsOn: [ - msi_ContributorRoleAssignment - ] + } + properties: { + azPowerShellVersion: '8.0' + retentionInterval: 'P1D' + arguments: '-ResourceGroupName ${resourceGroup().name} -SSHKeyName ${sshKeyName}' + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/New-SSHKey.ps1') + cleanupPreference: 'OnExpiration' + forceUpdateTag: utcValue + } + dependsOn: [ + msi_ContributorRoleAssignment + ] } @description('The public key to be added to the SSH Public Key resource.') diff --git a/avm/res/compute/ssh-public-key/tests/e2e/max/main.test.bicep b/avm/res/compute/ssh-public-key/tests/e2e/max/main.test.bicep index 41e4e6d25e..edacd11616 100644 --- a/avm/res/compute/ssh-public-key/tests/e2e/max/main.test.bicep +++ b/avm/res/compute/ssh-public-key/tests/e2e/max/main.test.bicep @@ -68,7 +68,10 @@ module testDeployment '../../../main.bicep' = { principalType: 'ServicePrincipal' } { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) principalId: nestedDependencies.outputs.managedIdentityPrincipalId principalType: 'ServicePrincipal' } diff --git a/avm/res/compute/ssh-public-key/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/compute/ssh-public-key/tests/e2e/waf-aligned/dependencies.bicep index 374cdd66a6..7de3a73841 100644 --- a/avm/res/compute/ssh-public-key/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/compute/ssh-public-key/tests/e2e/waf-aligned/dependencies.bicep @@ -14,41 +14,44 @@ param sshKeyName string param utcValue string = utcNow() resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } // required for the deployment script to create a new temporary ssh public key object resource msi_ContributorRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(resourceGroup().id, 'ManagedIdentityContributor', managedIdentityName) - properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor - principalId: managedIdentity.properties.principalId - principalType: 'ServicePrincipal' - } + name: guid(resourceGroup().id, 'ManagedIdentityContributor', managedIdentityName) + properties: { + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b24988ac-6180-42a0-ab88-20f7382dd24c' + ) // Contributor + principalId: managedIdentity.properties.principalId + principalType: 'ServicePrincipal' + } } resource createPubKeyScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { - name: generateSshPubKeyScriptName - location: location - kind: 'AzurePowerShell' - identity: { - type: 'UserAssigned' - userAssignedIdentities: { - '${managedIdentity.id}': {} - } - } - properties: { - azPowerShellVersion: '8.0' - retentionInterval: 'P1D' - arguments: '-ResourceGroupName ${resourceGroup().name} -SSHKeyName ${sshKeyName}' - scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/New-SSHKey.ps1') - cleanupPreference: 'OnExpiration' - forceUpdateTag: utcValue + name: generateSshPubKeyScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} } - dependsOn: [ - msi_ContributorRoleAssignment - ] + } + properties: { + azPowerShellVersion: '8.0' + retentionInterval: 'P1D' + arguments: '-ResourceGroupName ${resourceGroup().name} -SSHKeyName ${sshKeyName}' + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/New-SSHKey.ps1') + cleanupPreference: 'OnExpiration' + forceUpdateTag: utcValue + } + dependsOn: [ + msi_ContributorRoleAssignment + ] } @description('The public key to be added to the SSH Public Key resource.') diff --git a/avm/res/compute/ssh-public-key/tests/e2e/waf-aligned/main.test.bicep b/avm/res/compute/ssh-public-key/tests/e2e/waf-aligned/main.test.bicep index ed12fc9e2c..868248aa83 100644 --- a/avm/res/compute/ssh-public-key/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/compute/ssh-public-key/tests/e2e/waf-aligned/main.test.bicep @@ -69,7 +69,10 @@ module testDeployment '../../../main.bicep' = { principalType: 'ServicePrincipal' } { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) principalId: nestedDependencies.outputs.managedIdentityPrincipalId principalType: 'ServicePrincipal' } diff --git a/avm/res/compute/virtual-machine-scale-set/extension/main.json b/avm/res/compute/virtual-machine-scale-set/extension/main.json index 36751fb40e..936509ea01 100644 --- a/avm/res/compute/virtual-machine-scale-set/extension/main.json +++ b/avm/res/compute/virtual-machine-scale-set/extension/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3680417048986934448" + "version": "0.26.54.24096", + "templateHash": "8948100547542268397" }, "name": "Virtual Machine Scale Set Extensions", "description": "This module deploys a Virtual Machine Scale Set Extension.", diff --git a/avm/res/compute/virtual-machine-scale-set/main.bicep b/avm/res/compute/virtual-machine-scale-set/main.bicep index d9cdc509ca..0d4fc210a6 100644 --- a/avm/res/compute/virtual-machine-scale-set/main.bicep +++ b/avm/res/compute/virtual-machine-scale-set/main.bicep @@ -232,7 +232,7 @@ param skuName string param skuCapacity int = 1 @description('Optional. The virtual machine scale set zones. NOTE: Availability zones can only be set when you create the scale set.') -param availabilityZones array = [ 1, 2, 3 ] +param availabilityZones array = [1, 2, 3] @description('Optional. Tags of the resource.') param tags object? @@ -256,10 +256,12 @@ param sasTokenValidityLength string = 'PT8H' @description('Optional. The managed identity definition for this resource.') param managedIdentities managedIdentitiesType -var publicKeysFormatted = [for publicKey in publicKeys: { - path: publicKey.path - keyData: publicKey.keyData -}] +var publicKeysFormatted = [ + for publicKey in publicKeys: { + path: publicKey.path + keyData: publicKey.keyData + } +] var linuxConfiguration = { disablePasswordAuthentication: disablePasswordAuthentication @@ -274,9 +276,11 @@ var windowsConfiguration = { enableAutomaticUpdates: enableAutomaticUpdates timeZone: empty(timeZone) ? null : timeZone additionalUnattendContent: empty(additionalUnattendContent) ? null : additionalUnattendContent - winRM: !empty(winRM) ? { - listeners: winRM - } : null + winRM: !empty(winRM) + ? { + listeners: winRM + } + : null } var accountSasProperties = { @@ -287,53 +291,107 @@ var accountSasProperties = { signedProtocol: 'https' } -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 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 enableReferencedModulesTelemetry = false var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Data Operator for Managed Disks': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '959f8984-c045-4866-89c7-12bf9737be2e') - 'Desktop Virtualization Power On Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '489581de-a3bd-480d-9518-53dea7416b33') - 'Desktop Virtualization Power On Off Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '40c5ff49-9181-41f8-ae61-143b0e78555e') - 'Desktop Virtualization Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a959dbd1-f747-45e3-8ba6-dd80f235f97c') - 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') - 'Disk Backup Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e5e47e6-65f7-47ef-90b5-e5dd4d455f24') - 'Disk Pool Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60fc6e62-5479-42d4-8bf4-67625fcc2840') - 'Disk Restore Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b50d9833-a0cb-478e-945f-707fcc997c13') - 'Disk Snapshot Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce') + 'Data Operator for Managed Disks': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '959f8984-c045-4866-89c7-12bf9737be2e' + ) + 'Desktop Virtualization Power On Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '489581de-a3bd-480d-9518-53dea7416b33' + ) + 'Desktop Virtualization Power On Off Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '40c5ff49-9181-41f8-ae61-143b0e78555e' + ) + 'Desktop Virtualization Virtual Machine Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'a959dbd1-f747-45e3-8ba6-dd80f235f97c' + ) + 'DevTest Labs User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '76283e04-6283-4c54-8f91-bcf1374a3c64' + ) + 'Disk Backup Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '3e5e47e6-65f7-47ef-90b5-e5dd4d455f24' + ) + 'Disk Pool Operator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '60fc6e62-5479-42d4-8bf4-67625fcc2840' + ) + 'Disk Restore Operator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b50d9833-a0cb-478e-945f-707fcc997c13' + ) + 'Disk Snapshot Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '7efff54f-a5b4-42b5-a1c5-5411624893ce' + ) 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') - 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') - 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') - 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') - 'VM Scanner Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd24ecba3-c1f4-40fa-a7bb-4588a071e8fd') + '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' + ) + 'Virtual Machine Administrator Login': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '1c0163c0-47e6-4577-8991-ea5c82e286e4' + ) + 'Virtual Machine Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '9980e02c-c2be-4d73-94e8-173b1dc7cf3c' + ) + 'Virtual Machine User Login': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'fb879df8-f326-4884-b1cf-06f3ad86be52' + ) + 'VM Scanner Operator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'd24ecba3-c1f4-40fa-a7bb-4588a071e8fd' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.compute-virtualmachinescaleset.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.compute-virtualmachinescaleset.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource vmss 'Microsoft.Compute/virtualMachineScaleSets@2022-11-01' = { name: name @@ -342,9 +400,11 @@ resource vmss 'Microsoft.Compute/virtualMachineScaleSets@2022-11-01' = { identity: identity zones: availabilityZones properties: { - proximityPlacementGroup: !empty(proximityPlacementGroupResourceId) ? { - id: proximityPlacementGroupResourceId - } : null + proximityPlacementGroup: !empty(proximityPlacementGroupResourceId) + ? { + id: proximityPlacementGroupResourceId + } + : null upgradePolicy: { mode: upgradePolicyMode rollingUpgradePolicy: { @@ -375,10 +435,12 @@ resource vmss 'Microsoft.Compute/virtualMachineScaleSets@2022-11-01' = { securityProfile: { encryptionAtHost: encryptionAtHost ? encryptionAtHost : null securityType: securityType - uefiSettings: securityType == 'TrustedLaunch' ? { - secureBootEnabled: secureBootEnabled - vTpmEnabled: vTpmEnabled - } : null + uefiSettings: securityType == 'TrustedLaunch' + ? { + secureBootEnabled: secureBootEnabled + vTpmEnabled: vTpmEnabled + } + : null } storageProfile: { imageReference: imageReference @@ -393,52 +455,68 @@ resource vmss 'Microsoft.Compute/virtualMachineScaleSets@2022-11-01' = { vhdContainers: contains(osDisk, 'vhdContainers') ? osDisk.vhdContainers : null managedDisk: { storageAccountType: osDisk.managedDisk.storageAccountType - diskEncryptionSet: contains(osDisk.managedDisk, 'diskEncryptionSet') ? { - id: osDisk.managedDisk.diskEncryptionSet.id - } : null + diskEncryptionSet: contains(osDisk.managedDisk, 'diskEncryptionSet') + ? { + id: osDisk.managedDisk.diskEncryptionSet.id + } + : null } } - dataDisks: [for (dataDisk, index) in dataDisks: { - lun: index - diskSizeGB: dataDisk.diskSizeGB - createOption: dataDisk.createOption - caching: dataDisk.caching - writeAcceleratorEnabled: contains(osDisk, 'writeAcceleratorEnabled') ? osDisk.writeAcceleratorEnabled : null - managedDisk: { - storageAccountType: dataDisk.managedDisk.storageAccountType - diskEncryptionSet: contains(dataDisk.managedDisk, 'diskEncryptionSet') ? { - id: dataDisk.managedDisk.diskEncryptionSet.id - } : null + dataDisks: [ + for (dataDisk, index) in dataDisks: { + lun: index + diskSizeGB: dataDisk.diskSizeGB + createOption: dataDisk.createOption + caching: dataDisk.caching + writeAcceleratorEnabled: contains(osDisk, 'writeAcceleratorEnabled') ? osDisk.writeAcceleratorEnabled : null + managedDisk: { + storageAccountType: dataDisk.managedDisk.storageAccountType + diskEncryptionSet: contains(dataDisk.managedDisk, 'diskEncryptionSet') + ? { + id: dataDisk.managedDisk.diskEncryptionSet.id + } + : null + } + diskIOPSReadWrite: contains(osDisk, 'diskIOPSReadWrite') ? dataDisk.diskIOPSReadWrite : null + diskMBpsReadWrite: contains(osDisk, 'diskMBpsReadWrite') ? dataDisk.diskMBpsReadWrite : null } - diskIOPSReadWrite: contains(osDisk, 'diskIOPSReadWrite') ? dataDisk.diskIOPSReadWrite : null - diskMBpsReadWrite: contains(osDisk, 'diskMBpsReadWrite') ? dataDisk.diskMBpsReadWrite : null - }] + ] } networkProfile: { - networkInterfaceConfigurations: [for (nicConfiguration, index) in nicConfigurations: { - name: '${name}${nicConfiguration.nicSuffix}configuration-${index}' - properties: { - primary: (index == 0) ? true : any(null) - enableAcceleratedNetworking: contains(nicConfiguration, 'enableAcceleratedNetworking') ? nicConfiguration.enableAcceleratedNetworking : true - networkSecurityGroup: contains(nicConfiguration, 'nsgId') ? { - id: nicConfiguration.nsgId - } : null - ipConfigurations: nicConfiguration.ipConfigurations + networkInterfaceConfigurations: [ + for (nicConfiguration, index) in nicConfigurations: { + name: '${name}${nicConfiguration.nicSuffix}configuration-${index}' + properties: { + primary: (index == 0) ? true : any(null) + enableAcceleratedNetworking: contains(nicConfiguration, 'enableAcceleratedNetworking') + ? nicConfiguration.enableAcceleratedNetworking + : true + networkSecurityGroup: contains(nicConfiguration, 'nsgId') + ? { + id: nicConfiguration.nsgId + } + : null + ipConfigurations: nicConfiguration.ipConfigurations + } } - }] + ] } diagnosticsProfile: { bootDiagnostics: { enabled: !empty(bootDiagnosticStorageAccountName) - storageUri: !empty(bootDiagnosticStorageAccountName) ? 'https://${bootDiagnosticStorageAccountName}${bootDiagnosticStorageAccountUri}' : null + storageUri: !empty(bootDiagnosticStorageAccountName) + ? 'https://${bootDiagnosticStorageAccountName}${bootDiagnosticStorageAccountUri}' + : null } } licenseType: empty(licenseType) ? null : licenseType priority: vmPriority evictionPolicy: enableEvictionPolicy ? 'Deallocate' : null - billingProfile: !empty(vmPriority) && !empty(maxPriceForLowPriorityVm) ? { - maxPrice: maxPriceForLowPriorityVm - } : null + billingProfile: !empty(vmPriority) && !empty(maxPriceForLowPriorityVm) + ? { + maxPrice: maxPriceForLowPriorityVm + } + : null scheduledEventsProfile: scheduledEventsProfile } overprovision: overprovision @@ -458,196 +536,279 @@ resource vmss 'Microsoft.Compute/virtualMachineScaleSets@2022-11-01' = { plan: !empty(plan) ? plan : null } -module vmss_domainJoinExtension 'extension/main.bicep' = if (extensionDomainJoinConfig.enabled) { - name: '${uniqueString(deployment().name, location)}-VMSS-DomainJoin' - params: { - virtualMachineScaleSetName: vmss.name - name: 'DomainJoin' - publisher: 'Microsoft.Compute' - type: 'JsonADDomainExtension' - typeHandlerVersion: contains(extensionDomainJoinConfig, 'typeHandlerVersion') ? extensionDomainJoinConfig.typeHandlerVersion : '1.3' - autoUpgradeMinorVersion: contains(extensionDomainJoinConfig, 'autoUpgradeMinorVersion') ? extensionDomainJoinConfig.autoUpgradeMinorVersion : true - enableAutomaticUpgrade: contains(extensionDomainJoinConfig, 'enableAutomaticUpgrade') ? extensionDomainJoinConfig.enableAutomaticUpgrade : false - settings: extensionDomainJoinConfig.settings - protectedSettings: { - Password: extensionDomainJoinPassword +module vmss_domainJoinExtension 'extension/main.bicep' = + if (extensionDomainJoinConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-DomainJoin' + params: { + virtualMachineScaleSetName: vmss.name + name: 'DomainJoin' + publisher: 'Microsoft.Compute' + type: 'JsonADDomainExtension' + typeHandlerVersion: contains(extensionDomainJoinConfig, 'typeHandlerVersion') + ? extensionDomainJoinConfig.typeHandlerVersion + : '1.3' + autoUpgradeMinorVersion: contains(extensionDomainJoinConfig, 'autoUpgradeMinorVersion') + ? extensionDomainJoinConfig.autoUpgradeMinorVersion + : true + enableAutomaticUpgrade: contains(extensionDomainJoinConfig, 'enableAutomaticUpgrade') + ? extensionDomainJoinConfig.enableAutomaticUpgrade + : false + settings: extensionDomainJoinConfig.settings + protectedSettings: { + Password: extensionDomainJoinPassword + } } } -} -module vmss_microsoftAntiMalwareExtension 'extension/main.bicep' = if (extensionAntiMalwareConfig.enabled) { - name: '${uniqueString(deployment().name, location)}-VMSS-MicrosoftAntiMalware' - params: { - virtualMachineScaleSetName: vmss.name - name: 'MicrosoftAntiMalware' - publisher: 'Microsoft.Azure.Security' - type: 'IaaSAntimalware' - typeHandlerVersion: contains(extensionAntiMalwareConfig, 'typeHandlerVersion') ? extensionAntiMalwareConfig.typeHandlerVersion : '1.3' - autoUpgradeMinorVersion: contains(extensionAntiMalwareConfig, 'autoUpgradeMinorVersion') ? extensionAntiMalwareConfig.autoUpgradeMinorVersion : true - enableAutomaticUpgrade: contains(extensionAntiMalwareConfig, 'enableAutomaticUpgrade') ? extensionAntiMalwareConfig.enableAutomaticUpgrade : false - settings: extensionAntiMalwareConfig.settings +module vmss_microsoftAntiMalwareExtension 'extension/main.bicep' = + if (extensionAntiMalwareConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-MicrosoftAntiMalware' + params: { + virtualMachineScaleSetName: vmss.name + name: 'MicrosoftAntiMalware' + publisher: 'Microsoft.Azure.Security' + type: 'IaaSAntimalware' + typeHandlerVersion: contains(extensionAntiMalwareConfig, 'typeHandlerVersion') + ? extensionAntiMalwareConfig.typeHandlerVersion + : '1.3' + autoUpgradeMinorVersion: contains(extensionAntiMalwareConfig, 'autoUpgradeMinorVersion') + ? extensionAntiMalwareConfig.autoUpgradeMinorVersion + : true + enableAutomaticUpgrade: contains(extensionAntiMalwareConfig, 'enableAutomaticUpgrade') + ? extensionAntiMalwareConfig.enableAutomaticUpgrade + : false + settings: extensionAntiMalwareConfig.settings + } + dependsOn: [ + vmss_domainJoinExtension + ] } - dependsOn: [ - vmss_domainJoinExtension - ] -} -resource vmss_logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' existing = if (!empty(monitoringWorkspaceId)) { - name: last(split((!empty(monitoringWorkspaceId) ? monitoringWorkspaceId : 'law'), '/'))! - scope: az.resourceGroup(split((!empty(monitoringWorkspaceId) ? monitoringWorkspaceId : '//'), '/')[2], split((!empty(monitoringWorkspaceId) ? monitoringWorkspaceId : '////'), '/')[4]) -} +resource vmss_logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' existing = + if (!empty(monitoringWorkspaceId)) { + name: last(split((!empty(monitoringWorkspaceId) ? monitoringWorkspaceId : 'law'), '/'))! + scope: az.resourceGroup( + split((!empty(monitoringWorkspaceId) ? monitoringWorkspaceId : '//'), '/')[2], + split((!empty(monitoringWorkspaceId) ? monitoringWorkspaceId : '////'), '/')[4] + ) + } -module vmss_azureMonitorAgentExtension 'extension/main.bicep' = if (extensionMonitoringAgentConfig.enabled) { - name: '${uniqueString(deployment().name, location)}-VMSS-AzureMonitorAgent' - params: { - virtualMachineScaleSetName: vmss.name - name: 'AzureMonitorAgent' - publisher: 'Microsoft.Azure.Monitor' - type: osType == 'Windows' ? 'AzureMonitorWindowsAgent' : 'AzureMonitorLinuxAgent' - typeHandlerVersion: contains(extensionMonitoringAgentConfig, 'typeHandlerVersion') ? extensionMonitoringAgentConfig.typeHandlerVersion : (osType == 'Windows' ? '1.22' : '1.29') - autoUpgradeMinorVersion: contains(extensionMonitoringAgentConfig, 'autoUpgradeMinorVersion') ? extensionMonitoringAgentConfig.autoUpgradeMinorVersion : true - enableAutomaticUpgrade: contains(extensionMonitoringAgentConfig, 'enableAutomaticUpgrade') ? extensionMonitoringAgentConfig.enableAutomaticUpgrade : false - settings: { - workspaceId: !empty(monitoringWorkspaceId) ? reference(vmss_logAnalyticsWorkspace.id, vmss_logAnalyticsWorkspace.apiVersion).customerId : '' - GCS_AUTO_CONFIG: osType == 'Linux' ? true : null - } - protectedSettings: { - workspaceKey: !empty(monitoringWorkspaceId) ? vmss_logAnalyticsWorkspace.listKeys().primarySharedKey : '' +module vmss_azureMonitorAgentExtension 'extension/main.bicep' = + if (extensionMonitoringAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-AzureMonitorAgent' + params: { + virtualMachineScaleSetName: vmss.name + name: 'AzureMonitorAgent' + publisher: 'Microsoft.Azure.Monitor' + type: osType == 'Windows' ? 'AzureMonitorWindowsAgent' : 'AzureMonitorLinuxAgent' + typeHandlerVersion: contains(extensionMonitoringAgentConfig, 'typeHandlerVersion') + ? extensionMonitoringAgentConfig.typeHandlerVersion + : (osType == 'Windows' ? '1.22' : '1.29') + autoUpgradeMinorVersion: contains(extensionMonitoringAgentConfig, 'autoUpgradeMinorVersion') + ? extensionMonitoringAgentConfig.autoUpgradeMinorVersion + : true + enableAutomaticUpgrade: contains(extensionMonitoringAgentConfig, 'enableAutomaticUpgrade') + ? extensionMonitoringAgentConfig.enableAutomaticUpgrade + : false + settings: { + workspaceId: !empty(monitoringWorkspaceId) + ? reference(vmss_logAnalyticsWorkspace.id, vmss_logAnalyticsWorkspace.apiVersion).customerId + : '' + GCS_AUTO_CONFIG: osType == 'Linux' ? true : null + } + protectedSettings: { + workspaceKey: !empty(monitoringWorkspaceId) ? vmss_logAnalyticsWorkspace.listKeys().primarySharedKey : '' + } } + dependsOn: [ + vmss_microsoftAntiMalwareExtension + ] } - dependsOn: [ - vmss_microsoftAntiMalwareExtension - ] -} -module vmss_dependencyAgentExtension 'extension/main.bicep' = if (extensionDependencyAgentConfig.enabled) { - name: '${uniqueString(deployment().name, location)}-VMSS-DependencyAgent' - params: { - virtualMachineScaleSetName: vmss.name - name: 'DependencyAgent' - publisher: 'Microsoft.Azure.Monitoring.DependencyAgent' - type: osType == 'Windows' ? 'DependencyAgentWindows' : 'DependencyAgentLinux' - typeHandlerVersion: contains(extensionDependencyAgentConfig, 'typeHandlerVersion') ? extensionDependencyAgentConfig.typeHandlerVersion : '9.5' - autoUpgradeMinorVersion: contains(extensionDependencyAgentConfig, 'autoUpgradeMinorVersion') ? extensionDependencyAgentConfig.autoUpgradeMinorVersion : true - enableAutomaticUpgrade: contains(extensionDependencyAgentConfig, 'enableAutomaticUpgrade') ? extensionDependencyAgentConfig.enableAutomaticUpgrade : true +module vmss_dependencyAgentExtension 'extension/main.bicep' = + if (extensionDependencyAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-DependencyAgent' + params: { + virtualMachineScaleSetName: vmss.name + name: 'DependencyAgent' + publisher: 'Microsoft.Azure.Monitoring.DependencyAgent' + type: osType == 'Windows' ? 'DependencyAgentWindows' : 'DependencyAgentLinux' + typeHandlerVersion: contains(extensionDependencyAgentConfig, 'typeHandlerVersion') + ? extensionDependencyAgentConfig.typeHandlerVersion + : '9.5' + autoUpgradeMinorVersion: contains(extensionDependencyAgentConfig, 'autoUpgradeMinorVersion') + ? extensionDependencyAgentConfig.autoUpgradeMinorVersion + : true + enableAutomaticUpgrade: contains(extensionDependencyAgentConfig, 'enableAutomaticUpgrade') + ? extensionDependencyAgentConfig.enableAutomaticUpgrade + : true + } + dependsOn: [ + vmss_azureMonitorAgentExtension + ] } - dependsOn: [ - vmss_azureMonitorAgentExtension - ] -} -module vmss_networkWatcherAgentExtension 'extension/main.bicep' = if (extensionNetworkWatcherAgentConfig.enabled) { - name: '${uniqueString(deployment().name, location)}-VMSS-NetworkWatcherAgent' - params: { - virtualMachineScaleSetName: vmss.name - name: 'NetworkWatcherAgent' - publisher: 'Microsoft.Azure.NetworkWatcher' - type: osType == 'Windows' ? 'NetworkWatcherAgentWindows' : 'NetworkWatcherAgentLinux' - typeHandlerVersion: contains(extensionNetworkWatcherAgentConfig, 'typeHandlerVersion') ? extensionNetworkWatcherAgentConfig.typeHandlerVersion : '1.4' - autoUpgradeMinorVersion: contains(extensionNetworkWatcherAgentConfig, 'autoUpgradeMinorVersion') ? extensionNetworkWatcherAgentConfig.autoUpgradeMinorVersion : true - enableAutomaticUpgrade: contains(extensionNetworkWatcherAgentConfig, 'enableAutomaticUpgrade') ? extensionNetworkWatcherAgentConfig.enableAutomaticUpgrade : false +module vmss_networkWatcherAgentExtension 'extension/main.bicep' = + if (extensionNetworkWatcherAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-NetworkWatcherAgent' + params: { + virtualMachineScaleSetName: vmss.name + name: 'NetworkWatcherAgent' + publisher: 'Microsoft.Azure.NetworkWatcher' + type: osType == 'Windows' ? 'NetworkWatcherAgentWindows' : 'NetworkWatcherAgentLinux' + typeHandlerVersion: contains(extensionNetworkWatcherAgentConfig, 'typeHandlerVersion') + ? extensionNetworkWatcherAgentConfig.typeHandlerVersion + : '1.4' + autoUpgradeMinorVersion: contains(extensionNetworkWatcherAgentConfig, 'autoUpgradeMinorVersion') + ? extensionNetworkWatcherAgentConfig.autoUpgradeMinorVersion + : true + enableAutomaticUpgrade: contains(extensionNetworkWatcherAgentConfig, 'enableAutomaticUpgrade') + ? extensionNetworkWatcherAgentConfig.enableAutomaticUpgrade + : false + } + dependsOn: [ + vmss_dependencyAgentExtension + ] } - dependsOn: [ - vmss_dependencyAgentExtension - ] -} -module vmss_desiredStateConfigurationExtension 'extension/main.bicep' = if (extensionDSCConfig.enabled) { - name: '${uniqueString(deployment().name, location)}-VMSS-DesiredStateConfiguration' - params: { - virtualMachineScaleSetName: vmss.name - name: 'DesiredStateConfiguration' - publisher: 'Microsoft.Powershell' - type: 'DSC' - typeHandlerVersion: contains(extensionDSCConfig, 'typeHandlerVersion') ? extensionDSCConfig.typeHandlerVersion : '2.77' - autoUpgradeMinorVersion: contains(extensionDSCConfig, 'autoUpgradeMinorVersion') ? extensionDSCConfig.autoUpgradeMinorVersion : true - enableAutomaticUpgrade: contains(extensionDSCConfig, 'enableAutomaticUpgrade') ? extensionDSCConfig.enableAutomaticUpgrade : false - settings: contains(extensionDSCConfig, 'settings') ? extensionDSCConfig.settings : {} - protectedSettings: contains(extensionDSCConfig, 'protectedSettings') ? extensionDSCConfig.protectedSettings : {} +module vmss_desiredStateConfigurationExtension 'extension/main.bicep' = + if (extensionDSCConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-DesiredStateConfiguration' + params: { + virtualMachineScaleSetName: vmss.name + name: 'DesiredStateConfiguration' + publisher: 'Microsoft.Powershell' + type: 'DSC' + typeHandlerVersion: contains(extensionDSCConfig, 'typeHandlerVersion') + ? extensionDSCConfig.typeHandlerVersion + : '2.77' + autoUpgradeMinorVersion: contains(extensionDSCConfig, 'autoUpgradeMinorVersion') + ? extensionDSCConfig.autoUpgradeMinorVersion + : true + enableAutomaticUpgrade: contains(extensionDSCConfig, 'enableAutomaticUpgrade') + ? extensionDSCConfig.enableAutomaticUpgrade + : false + settings: contains(extensionDSCConfig, 'settings') ? extensionDSCConfig.settings : {} + protectedSettings: contains(extensionDSCConfig, 'protectedSettings') ? extensionDSCConfig.protectedSettings : {} + } + dependsOn: [ + vmss_networkWatcherAgentExtension + ] } - dependsOn: [ - vmss_networkWatcherAgentExtension - ] -} -module vmss_customScriptExtension 'extension/main.bicep' = if (extensionCustomScriptConfig.enabled) { - name: '${uniqueString(deployment().name, location)}-VMSS-CustomScriptExtension' - params: { - virtualMachineScaleSetName: vmss.name - name: 'CustomScriptExtension' - publisher: osType == 'Windows' ? 'Microsoft.Compute' : 'Microsoft.Azure.Extensions' - type: osType == 'Windows' ? 'CustomScriptExtension' : 'CustomScript' - typeHandlerVersion: contains(extensionCustomScriptConfig, 'typeHandlerVersion') ? extensionCustomScriptConfig.typeHandlerVersion : (osType == 'Windows' ? '1.10' : '2.1') - autoUpgradeMinorVersion: contains(extensionCustomScriptConfig, 'autoUpgradeMinorVersion') ? extensionCustomScriptConfig.autoUpgradeMinorVersion : true - enableAutomaticUpgrade: contains(extensionCustomScriptConfig, 'enableAutomaticUpgrade') ? extensionCustomScriptConfig.enableAutomaticUpgrade : false - settings: { - fileUris: [for fileData in extensionCustomScriptConfig.fileData: contains(fileData, 'storageAccountId') ? '${fileData.uri}?${listAccountSas(fileData.storageAccountId, '2019-04-01', accountSasProperties).accountSasToken}' : fileData.uri] +module vmss_customScriptExtension 'extension/main.bicep' = + if (extensionCustomScriptConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-CustomScriptExtension' + params: { + virtualMachineScaleSetName: vmss.name + name: 'CustomScriptExtension' + publisher: osType == 'Windows' ? 'Microsoft.Compute' : 'Microsoft.Azure.Extensions' + type: osType == 'Windows' ? 'CustomScriptExtension' : 'CustomScript' + typeHandlerVersion: contains(extensionCustomScriptConfig, 'typeHandlerVersion') + ? extensionCustomScriptConfig.typeHandlerVersion + : (osType == 'Windows' ? '1.10' : '2.1') + autoUpgradeMinorVersion: contains(extensionCustomScriptConfig, 'autoUpgradeMinorVersion') + ? extensionCustomScriptConfig.autoUpgradeMinorVersion + : true + enableAutomaticUpgrade: contains(extensionCustomScriptConfig, 'enableAutomaticUpgrade') + ? extensionCustomScriptConfig.enableAutomaticUpgrade + : false + settings: { + fileUris: [ + for fileData in extensionCustomScriptConfig.fileData: contains(fileData, 'storageAccountId') + ? '${fileData.uri}?${listAccountSas(fileData.storageAccountId, '2019-04-01', accountSasProperties).accountSasToken}' + : fileData.uri + ] + } + protectedSettings: contains(extensionCustomScriptConfig, 'protectedSettings') + ? extensionCustomScriptConfig.protectedSettings + : {} } - protectedSettings: contains(extensionCustomScriptConfig, 'protectedSettings') ? extensionCustomScriptConfig.protectedSettings : {} + dependsOn: [ + vmss_desiredStateConfigurationExtension + ] } - dependsOn: [ - vmss_desiredStateConfigurationExtension - ] -} -module vmss_azureDiskEncryptionExtension 'extension/main.bicep' = if (extensionAzureDiskEncryptionConfig.enabled) { - name: '${uniqueString(deployment().name, location)}-VMSS-AzureDiskEncryption' - params: { - virtualMachineScaleSetName: vmss.name - name: 'AzureDiskEncryption' - publisher: 'Microsoft.Azure.Security' - type: osType == 'Windows' ? 'AzureDiskEncryption' : 'AzureDiskEncryptionForLinux' - typeHandlerVersion: contains(extensionAzureDiskEncryptionConfig, 'typeHandlerVersion') ? extensionAzureDiskEncryptionConfig.typeHandlerVersion : (osType == 'Windows' ? '2.2' : '1.1') - autoUpgradeMinorVersion: contains(extensionAzureDiskEncryptionConfig, 'autoUpgradeMinorVersion') ? extensionAzureDiskEncryptionConfig.autoUpgradeMinorVersion : true - enableAutomaticUpgrade: contains(extensionAzureDiskEncryptionConfig, 'enableAutomaticUpgrade') ? extensionAzureDiskEncryptionConfig.enableAutomaticUpgrade : false - forceUpdateTag: contains(extensionAzureDiskEncryptionConfig, 'forceUpdateTag') ? extensionAzureDiskEncryptionConfig.forceUpdateTag : '1.0' - settings: extensionAzureDiskEncryptionConfig.settings +module vmss_azureDiskEncryptionExtension 'extension/main.bicep' = + if (extensionAzureDiskEncryptionConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-AzureDiskEncryption' + params: { + virtualMachineScaleSetName: vmss.name + name: 'AzureDiskEncryption' + publisher: 'Microsoft.Azure.Security' + type: osType == 'Windows' ? 'AzureDiskEncryption' : 'AzureDiskEncryptionForLinux' + typeHandlerVersion: contains(extensionAzureDiskEncryptionConfig, 'typeHandlerVersion') + ? extensionAzureDiskEncryptionConfig.typeHandlerVersion + : (osType == 'Windows' ? '2.2' : '1.1') + autoUpgradeMinorVersion: contains(extensionAzureDiskEncryptionConfig, 'autoUpgradeMinorVersion') + ? extensionAzureDiskEncryptionConfig.autoUpgradeMinorVersion + : true + enableAutomaticUpgrade: contains(extensionAzureDiskEncryptionConfig, 'enableAutomaticUpgrade') + ? extensionAzureDiskEncryptionConfig.enableAutomaticUpgrade + : false + forceUpdateTag: contains(extensionAzureDiskEncryptionConfig, 'forceUpdateTag') + ? extensionAzureDiskEncryptionConfig.forceUpdateTag + : '1.0' + settings: extensionAzureDiskEncryptionConfig.settings + } + dependsOn: [ + vmss_customScriptExtension + ] } - dependsOn: [ - vmss_customScriptExtension - ] -} -resource vmss_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.' +resource vmss_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: vmss } - scope: vmss -} -resource vmss_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource vmss_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: vmss } - scope: vmss -}] - -resource vmss_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(vmss.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +] + +resource vmss_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(vmss.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: vmss } - scope: vmss -}] +] @description('The resource ID of the virtual machine scale set.') output resourceId string = vmss.id diff --git a/avm/res/compute/virtual-machine-scale-set/main.json b/avm/res/compute/virtual-machine-scale-set/main.json index 631b4efcc3..518c5e8df8 100644 --- a/avm/res/compute/virtual-machine-scale-set/main.json +++ b/avm/res/compute/virtual-machine-scale-set/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14475705222828543049" + "version": "0.26.54.24096", + "templateHash": "15325819648954627762" }, "name": "Virtual Machine Scale Sets", "description": "This module deploys a Virtual Machine Scale Set.", @@ -1054,8 +1054,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3680417048986934448" + "version": "0.26.54.24096", + "templateHash": "8948100547542268397" }, "name": "Virtual Machine Scale Set Extensions", "description": "This module deploys a Virtual Machine Scale Set Extension.", @@ -1216,8 +1216,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3680417048986934448" + "version": "0.26.54.24096", + "templateHash": "8948100547542268397" }, "name": "Virtual Machine Scale Set Extensions", "description": "This module deploys a Virtual Machine Scale Set Extension.", @@ -1385,8 +1385,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3680417048986934448" + "version": "0.26.54.24096", + "templateHash": "8948100547542268397" }, "name": "Virtual Machine Scale Set Extensions", "description": "This module deploys a Virtual Machine Scale Set Extension.", @@ -1544,8 +1544,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3680417048986934448" + "version": "0.26.54.24096", + "templateHash": "8948100547542268397" }, "name": "Virtual Machine Scale Set Extensions", "description": "This module deploys a Virtual Machine Scale Set Extension.", @@ -1702,8 +1702,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3680417048986934448" + "version": "0.26.54.24096", + "templateHash": "8948100547542268397" }, "name": "Virtual Machine Scale Set Extensions", "description": "This module deploys a Virtual Machine Scale Set Extension.", @@ -1864,8 +1864,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3680417048986934448" + "version": "0.26.54.24096", + "templateHash": "8948100547542268397" }, "name": "Virtual Machine Scale Set Extensions", "description": "This module deploys a Virtual Machine Scale Set Extension.", @@ -2032,8 +2032,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3680417048986934448" + "version": "0.26.54.24096", + "templateHash": "8948100547542268397" }, "name": "Virtual Machine Scale Set Extensions", "description": "This module deploys a Virtual Machine Scale Set Extension.", @@ -2194,8 +2194,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3680417048986934448" + "version": "0.26.54.24096", + "templateHash": "8948100547542268397" }, "name": "Virtual Machine Scale Set Extensions", "description": "This module deploys a Virtual Machine Scale Set Extension.", diff --git a/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.defaults/dependencies.bicep b/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.defaults/dependencies.bicep index 9edda99f16..a7e3e62938 100644 --- a/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.defaults/dependencies.bicep +++ b/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.defaults/dependencies.bicep @@ -45,7 +45,10 @@ resource msiRGContrRoleAssignment 'Microsoft.Authorization/roleAssignments@2022- scope: resourceGroup() properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b24988ac-6180-42a0-ab88-20f7382dd24c' + ) // Contributor principalType: 'ServicePrincipal' } } diff --git a/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.defaults/main.test.bicep b/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.defaults/main.test.bicep index e775db83ba..f2bda65417 100644 --- a/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.defaults/main.test.bicep +++ b/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.defaults/main.test.bicep @@ -48,49 +48,51 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - adminUsername: 'scaleSetAdmin' - imageReference: { - publisher: 'Canonical' - offer: '0001-com-ubuntu-server-jammy' - sku: '22_04-lts-gen2' - version: 'latest' - } - osDisk: { - createOption: 'fromImage' - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + adminUsername: 'scaleSetAdmin' + imageReference: { + publisher: 'Canonical' + offer: '0001-com-ubuntu-server-jammy' + sku: '22_04-lts-gen2' + version: 'latest' } - } - osType: 'Linux' - skuName: 'Standard_B12ms' - disablePasswordAuthentication: true - nicConfigurations: [ - { - ipConfigurations: [ - { - name: 'ipconfig1' - properties: { - subnet: { - id: nestedDependencies.outputs.subnetResourceId + osDisk: { + createOption: 'fromImage' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Linux' + skuName: 'Standard_B12ms' + disablePasswordAuthentication: true + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig1' + properties: { + subnet: { + id: nestedDependencies.outputs.subnetResourceId + } } } - } - ] - nicSuffix: '-nic01' - } - ] - publicKeys: [ - { - keyData: nestedDependencies.outputs.SSHKeyPublicKey - path: '/home/scaleSetAdmin/.ssh/authorized_keys' - } - ] + ] + nicSuffix: '-nic01' + } + ] + publicKeys: [ + { + keyData: nestedDependencies.outputs.SSHKeyPublicKey + path: '/home/scaleSetAdmin/.ssh/authorized_keys' + } + ] + } } -}] +] diff --git a/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.max/dependencies.bicep b/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.max/dependencies.bicep index cb6cff2726..65cf9669af 100644 --- a/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.max/dependencies.bicep +++ b/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.max/dependencies.bicep @@ -80,7 +80,10 @@ resource msiRGContrRoleAssignment 'Microsoft.Authorization/roleAssignments@2022- scope: resourceGroup() properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b24988ac-6180-42a0-ab88-20f7382dd24c' + ) // Contributor principalType: 'ServicePrincipal' } } @@ -90,7 +93,10 @@ resource msiKVCryptoUserRoleAssignment 'Microsoft.Authorization/roleAssignments@ scope: keyVault::key properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '12338af0-0e69-4776-bea7-57ae8d297424' + ) // Key Vault Crypto User principalType: 'ServicePrincipal' } } diff --git a/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.max/main.test.bicep b/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.max/main.test.bicep index 80b7f9e661..1794bd0571 100644 --- a/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.max/main.test.bicep +++ b/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.max/main.test.bicep @@ -65,147 +65,149 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - adminUsername: 'scaleSetAdmin' - imageReference: { - publisher: 'Canonical' - offer: '0001-com-ubuntu-server-jammy' - sku: '22_04-lts-gen2' - version: 'latest' - } - osDisk: { - createOption: 'fromImage' - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' - } - } - osType: 'Linux' - skuName: 'Standard_B12ms' - availabilityZones: [ - '2' - ] - bootDiagnosticStorageAccountName: nestedDependencies.outputs.storageAccountName - dataDisks: [ - { - caching: 'ReadOnly' - createOption: 'Empty' - diskSizeGB: '256' - managedDisk: { - storageAccountType: 'Premium_LRS' - } +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + adminUsername: 'scaleSetAdmin' + imageReference: { + publisher: 'Canonical' + offer: '0001-com-ubuntu-server-jammy' + sku: '22_04-lts-gen2' + version: 'latest' } - { - caching: 'ReadOnly' - createOption: 'Empty' + osDisk: { + createOption: 'fromImage' diskSizeGB: '128' managedDisk: { storageAccountType: 'Premium_LRS' } } - ] - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ + osType: 'Linux' + skuName: 'Standard_B12ms' + availabilityZones: [ + '2' + ] + bootDiagnosticStorageAccountName: nestedDependencies.outputs.storageAccountName + dataDisks: [ + { + caching: 'ReadOnly' + createOption: 'Empty' + diskSizeGB: '256' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + { + caching: 'ReadOnly' + createOption: 'Empty' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + ] + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + disablePasswordAuthentication: true + encryptionAtHost: false + extensionCustomScriptConfig: { + enabled: true + fileData: [ { - category: 'AllMetrics' + storageAccountId: nestedDependencies.outputs.storageAccountResourceId + uri: nestedDependencies.outputs.storageAccountCSEFileUrl } ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + protectedSettings: { + commandToExecute: 'sudo apt-get update' + } } - ] - disablePasswordAuthentication: true - encryptionAtHost: false - extensionCustomScriptConfig: { - enabled: true - fileData: [ - { - storageAccountId: nestedDependencies.outputs.storageAccountResourceId - uri: nestedDependencies.outputs.storageAccountCSEFileUrl + extensionDependencyAgentConfig: { + enabled: true + } + extensionAzureDiskEncryptionConfig: { + enabled: true + settings: { + EncryptionOperation: 'EnableEncryption' + KekVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + KeyEncryptionAlgorithm: 'RSA-OAEP' + KeyEncryptionKeyURL: nestedDependencies.outputs.keyVaultEncryptionKeyUrl + KeyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + KeyVaultURL: nestedDependencies.outputs.keyVaultUrl + ResizeOSDisk: 'false' + VolumeType: 'All' } - ] - protectedSettings: { - commandToExecute: 'sudo apt-get update' } - } - extensionDependencyAgentConfig: { - enabled: true - } - extensionAzureDiskEncryptionConfig: { - enabled: true - settings: { - EncryptionOperation: 'EnableEncryption' - KekVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - KeyEncryptionAlgorithm: 'RSA-OAEP' - KeyEncryptionKeyURL: nestedDependencies.outputs.keyVaultEncryptionKeyUrl - KeyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - KeyVaultURL: nestedDependencies.outputs.keyVaultUrl - ResizeOSDisk: 'false' - VolumeType: 'All' + extensionMonitoringAgentConfig: { + enabled: true } - } - extensionMonitoringAgentConfig: { - enabled: true - } - extensionNetworkWatcherAgentConfig: { - enabled: true - } - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - nicConfigurations: [ - { - ipConfigurations: [ - { - name: 'ipconfig1' - properties: { - subnet: { - id: nestedDependencies.outputs.subnetResourceId + extensionNetworkWatcherAgentConfig: { + enabled: true + } + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig1' + properties: { + subnet: { + id: nestedDependencies.outputs.subnetResourceId + } } } - } + ] + nicSuffix: '-nic01' + } + ] + publicKeys: [ + { + keyData: nestedDependencies.outputs.SSHKeyPublicKey + path: '/home/scaleSetAdmin/.ssh/authorized_keys' + } + ] + roleAssignments: [ + { + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + roleDefinitionIdOrName: 'Reader' + principalType: 'ServicePrincipal' + } + ] + scaleSetFaultDomain: 1 + skuCapacity: 1 + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId ] - nicSuffix: '-nic01' - } - ] - publicKeys: [ - { - keyData: nestedDependencies.outputs.SSHKeyPublicKey - path: '/home/scaleSetAdmin/.ssh/authorized_keys' } - ] - roleAssignments: [ - { - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - roleDefinitionIdOrName: 'Reader' - principalType: 'ServicePrincipal' + upgradePolicyMode: 'Manual' + vmNamePrefix: 'vmsslinvm' + vmPriority: 'Regular' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - scaleSetFaultDomain: 1 - skuCapacity: 1 - managedIdentities: { - systemAssigned: true - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - upgradePolicyMode: 'Manual' - vmNamePrefix: 'vmsslinvm' - vmPriority: 'Regular' - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.ssecmk/dependencies.bicep b/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.ssecmk/dependencies.bicep index c6780826ea..324e66e29f 100644 --- a/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.ssecmk/dependencies.bicep +++ b/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.ssecmk/dependencies.bicep @@ -89,7 +89,10 @@ resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { scope: keyVault properties: { principalId: diskEncryptionSet.identity.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6') // Key Vault Crypto Service Encryption User + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'e147488a-f6f5-4113-8e2d-b22465e65bf6' + ) // Key Vault Crypto Service Encryption User principalType: 'ServicePrincipal' } } @@ -104,7 +107,10 @@ resource msiRGContrRoleAssignment 'Microsoft.Authorization/roleAssignments@2022- scope: resourceGroup() properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b24988ac-6180-42a0-ab88-20f7382dd24c' + ) // Contributor principalType: 'ServicePrincipal' } } diff --git a/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.ssecmk/main.test.bicep b/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.ssecmk/main.test.bicep index b071b2f69c..035f41d15f 100644 --- a/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.ssecmk/main.test.bicep +++ b/avm/res/compute/virtual-machine-scale-set/tests/e2e/linux.ssecmk/main.test.bicep @@ -53,51 +53,40 @@ module nestedDependencies 'dependencies.bicep' = { // Test Execution // // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - extensionMonitoringAgentConfig: { - enabled: true - } - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - adminUsername: 'scaleSetAdmin' - imageReference: { - publisher: 'Canonical' - offer: '0001-com-ubuntu-server-jammy' - sku: '22_04-lts-gen2' - version: 'latest' - } - nicConfigurations: [ - { - ipConfigurations: [ - { - name: 'ipconfig1' - properties: { - subnet: { - id: nestedDependencies.outputs.subnetResourceId +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + extensionMonitoringAgentConfig: { + enabled: true + } + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + adminUsername: 'scaleSetAdmin' + imageReference: { + publisher: 'Canonical' + offer: '0001-com-ubuntu-server-jammy' + sku: '22_04-lts-gen2' + version: 'latest' + } + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig1' + properties: { + subnet: { + id: nestedDependencies.outputs.subnetResourceId + } } } - } - ] - nicSuffix: '-nic01' - } - ] - osDisk: { - createOption: 'fromImage' - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' - diskEncryptionSet: { - id: nestedDependencies.outputs.diskEncryptionSetResourceId + ] + nicSuffix: '-nic01' } - } - } - dataDisks: [ - { - caching: 'ReadOnly' - createOption: 'Empty' + ] + osDisk: { + createOption: 'fromImage' diskSizeGB: '128' managedDisk: { storageAccountType: 'Premium_LRS' @@ -106,15 +95,28 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' } } } - ] - osType: 'Linux' - skuName: 'Standard_B12ms' - disablePasswordAuthentication: true - publicKeys: [ - { - keyData: nestedDependencies.outputs.SSHKeyPublicKey - path: '/home/scaleSetAdmin/.ssh/authorized_keys' - } - ] + dataDisks: [ + { + caching: 'ReadOnly' + createOption: 'Empty' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + diskEncryptionSet: { + id: nestedDependencies.outputs.diskEncryptionSetResourceId + } + } + } + ] + osType: 'Linux' + skuName: 'Standard_B12ms' + disablePasswordAuthentication: true + publicKeys: [ + { + keyData: nestedDependencies.outputs.SSHKeyPublicKey + path: '/home/scaleSetAdmin/.ssh/authorized_keys' + } + ] + } } -}] +] diff --git a/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.defaults/main.test.bicep b/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.defaults/main.test.bicep index 8275ac5bef..085ffb5828 100644 --- a/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.defaults/main.test.bicep +++ b/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.defaults/main.test.bicep @@ -49,43 +49,45 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - adminUsername: 'localAdminUser' - adminPassword: password - imageReference: { - publisher: 'MicrosoftWindowsServer' - offer: 'WindowsServer' - sku: '2022-datacenter-azure-edition' - version: 'latest' - } - osDisk: { - createOption: 'fromImage' - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + adminUsername: 'localAdminUser' + adminPassword: password + imageReference: { + publisher: 'MicrosoftWindowsServer' + offer: 'WindowsServer' + sku: '2022-datacenter-azure-edition' + version: 'latest' } - } - osType: 'Windows' - skuName: 'Standard_B12ms' - nicConfigurations: [ - { - ipConfigurations: [ - { - name: 'ipconfig1' - properties: { - subnet: { - id: nestedDependencies.outputs.subnetResourceId + osDisk: { + createOption: 'fromImage' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Windows' + skuName: 'Standard_B12ms' + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig1' + properties: { + subnet: { + id: nestedDependencies.outputs.subnetResourceId + } } } - } - ] - nicSuffix: '-nic01' - } - ] + ] + nicSuffix: '-nic01' + } + ] + } } -}] +] diff --git a/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.max/dependencies.bicep b/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.max/dependencies.bicep index 2b1b70bb91..38258f3bc7 100644 --- a/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.max/dependencies.bicep +++ b/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.max/dependencies.bicep @@ -74,7 +74,10 @@ resource msiRGContrRoleAssignment 'Microsoft.Authorization/roleAssignments@2022- scope: resourceGroup() properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b24988ac-6180-42a0-ab88-20f7382dd24c' + ) // Contributor principalType: 'ServicePrincipal' } } @@ -84,7 +87,10 @@ resource msiKVCryptoUserRoleAssignment 'Microsoft.Authorization/roleAssignments@ scope: keyVault::key properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '12338af0-0e69-4776-bea7-57ae8d297424' + ) // Key Vault Crypto User principalType: 'ServicePrincipal' } } diff --git a/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.max/main.test.bicep b/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.max/main.test.bicep index d3524669f6..ecc12d03d8 100644 --- a/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.max/main.test.bicep +++ b/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.max/main.test.bicep @@ -67,139 +67,141 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - adminUsername: 'localAdminUser' - imageReference: { - publisher: 'MicrosoftWindowsServer' - offer: 'WindowsServer' - sku: '2022-datacenter-azure-edition' - version: 'latest' - } - osDisk: { - createOption: 'fromImage' - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + adminUsername: 'localAdminUser' + imageReference: { + publisher: 'MicrosoftWindowsServer' + offer: 'WindowsServer' + sku: '2022-datacenter-azure-edition' + version: 'latest' } - } - osType: 'Windows' - skuName: 'Standard_B12ms' - adminPassword: password - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ + osDisk: { + createOption: 'fromImage' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Windows' + skuName: 'Standard_B12ms' + adminPassword: password + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + encryptionAtHost: false + extensionAntiMalwareConfig: { + enabled: true + settings: { + AntimalwareEnabled: true + Exclusions: { + Extensions: '.log;.ldf' + Paths: 'D:\\IISlogs;D:\\DatabaseLogs' + Processes: 'mssence.svc' + } + RealtimeProtectionEnabled: true + ScheduledScanSettings: { + day: '7' + isEnabled: 'true' + scanType: 'Quick' + time: '120' + } + } + } + extensionCustomScriptConfig: { + enabled: true + fileData: [ { - category: 'AllMetrics' + storageAccountId: nestedDependencies.outputs.storageAccountResourceId + uri: nestedDependencies.outputs.storageAccountCSEFileUrl } ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - encryptionAtHost: false - extensionAntiMalwareConfig: { - enabled: true - settings: { - AntimalwareEnabled: true - Exclusions: { - Extensions: '.log;.ldf' - Paths: 'D:\\IISlogs;D:\\DatabaseLogs' - Processes: 'mssence.svc' - } - RealtimeProtectionEnabled: true - ScheduledScanSettings: { - day: '7' - isEnabled: 'true' - scanType: 'Quick' - time: '120' + protectedSettings: { + commandToExecute: 'powershell -ExecutionPolicy Unrestricted -Command "& ./${nestedDependencies.outputs.storageAccountCSEFileName}"' } } - } - extensionCustomScriptConfig: { - enabled: true - fileData: [ - { - storageAccountId: nestedDependencies.outputs.storageAccountResourceId - uri: nestedDependencies.outputs.storageAccountCSEFileUrl + extensionDependencyAgentConfig: { + enabled: true + } + extensionAzureDiskEncryptionConfig: { + enabled: true + settings: { + EncryptionOperation: 'EnableEncryption' + KekVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + KeyEncryptionAlgorithm: 'RSA-OAEP' + KeyEncryptionKeyURL: nestedDependencies.outputs.keyVaultEncryptionKeyUrl + KeyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + KeyVaultURL: nestedDependencies.outputs.keyVaultUrl + ResizeOSDisk: 'false' + VolumeType: 'All' } - ] - protectedSettings: { - commandToExecute: 'powershell -ExecutionPolicy Unrestricted -Command "& ./${nestedDependencies.outputs.storageAccountCSEFileName}"' } - } - extensionDependencyAgentConfig: { - enabled: true - } - extensionAzureDiskEncryptionConfig: { - enabled: true - settings: { - EncryptionOperation: 'EnableEncryption' - KekVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - KeyEncryptionAlgorithm: 'RSA-OAEP' - KeyEncryptionKeyURL: nestedDependencies.outputs.keyVaultEncryptionKeyUrl - KeyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - KeyVaultURL: nestedDependencies.outputs.keyVaultUrl - ResizeOSDisk: 'false' - VolumeType: 'All' + extensionDSCConfig: { + enabled: true } - } - extensionDSCConfig: { - enabled: true - } - extensionMonitoringAgentConfig: { - enabled: true - } - extensionNetworkWatcherAgentConfig: { - enabled: true - } - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - nicConfigurations: [ - { - ipConfigurations: [ - { - name: 'ipconfig1' - properties: { - subnet: { - id: nestedDependencies.outputs.subnetResourceId + extensionMonitoringAgentConfig: { + enabled: true + } + extensionNetworkWatcherAgentConfig: { + enabled: true + } + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig1' + properties: { + subnet: { + id: nestedDependencies.outputs.subnetResourceId + } } } - } + ] + nicSuffix: '-nic01' + } + ] + roleAssignments: [ + { + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + roleDefinitionIdOrName: 'Reader' + principalType: 'ServicePrincipal' + } + ] + skuCapacity: 1 + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId ] - nicSuffix: '-nic01' } - ] - roleAssignments: [ - { - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - roleDefinitionIdOrName: 'Reader' - principalType: 'ServicePrincipal' + upgradePolicyMode: 'Manual' + vmNamePrefix: 'vmsswinvm' + vmPriority: 'Regular' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - skuCapacity: 1 - managedIdentities: { - systemAssigned: true - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - upgradePolicyMode: 'Manual' - vmNamePrefix: 'vmsswinvm' - vmPriority: 'Regular' - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.waf-aligned/dependencies.bicep b/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.waf-aligned/dependencies.bicep index 2b1b70bb91..38258f3bc7 100644 --- a/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.waf-aligned/dependencies.bicep +++ b/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.waf-aligned/dependencies.bicep @@ -74,7 +74,10 @@ resource msiRGContrRoleAssignment 'Microsoft.Authorization/roleAssignments@2022- scope: resourceGroup() properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b24988ac-6180-42a0-ab88-20f7382dd24c' + ) // Contributor principalType: 'ServicePrincipal' } } @@ -84,7 +87,10 @@ resource msiKVCryptoUserRoleAssignment 'Microsoft.Authorization/roleAssignments@ scope: keyVault::key properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '12338af0-0e69-4776-bea7-57ae8d297424' + ) // Key Vault Crypto User principalType: 'ServicePrincipal' } } diff --git a/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.waf-aligned/main.test.bicep b/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.waf-aligned/main.test.bicep index 337487ca49..761f393356 100644 --- a/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.waf-aligned/main.test.bicep +++ b/avm/res/compute/virtual-machine-scale-set/tests/e2e/windows.waf-aligned/main.test.bicep @@ -67,128 +67,130 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - adminUsername: 'localAdminUser' - imageReference: { - publisher: 'MicrosoftWindowsServer' - offer: 'WindowsServer' - sku: '2022-datacenter-azure-edition' - version: 'latest' - } - osDisk: { - createOption: 'fromImage' - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + adminUsername: 'localAdminUser' + imageReference: { + publisher: 'MicrosoftWindowsServer' + offer: 'WindowsServer' + sku: '2022-datacenter-azure-edition' + version: 'latest' } - } - osType: 'Windows' - skuName: 'Standard_B12ms' - adminPassword: password - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ + osDisk: { + createOption: 'fromImage' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Windows' + skuName: 'Standard_B12ms' + adminPassword: password + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + encryptionAtHost: false // Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your virtual machine scale sets. + extensionAntiMalwareConfig: { + enabled: true + settings: { + AntimalwareEnabled: true + Exclusions: { + Extensions: '.log;.ldf' + Paths: 'D:\\IISlogs;D:\\DatabaseLogs' + Processes: 'mssence.svc' + } + RealtimeProtectionEnabled: true + ScheduledScanSettings: { + day: '7' + isEnabled: 'true' + scanType: 'Quick' + time: '120' + } + } + } + extensionCustomScriptConfig: { + enabled: true + fileData: [ { - category: 'AllMetrics' + storageAccountId: nestedDependencies.outputs.storageAccountResourceId + uri: nestedDependencies.outputs.storageAccountCSEFileUrl } ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - encryptionAtHost: false // Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your virtual machine scale sets. - extensionAntiMalwareConfig: { - enabled: true - settings: { - AntimalwareEnabled: true - Exclusions: { - Extensions: '.log;.ldf' - Paths: 'D:\\IISlogs;D:\\DatabaseLogs' - Processes: 'mssence.svc' - } - RealtimeProtectionEnabled: true - ScheduledScanSettings: { - day: '7' - isEnabled: 'true' - scanType: 'Quick' - time: '120' + protectedSettings: { + commandToExecute: 'powershell -ExecutionPolicy Unrestricted -Command "& ./${nestedDependencies.outputs.storageAccountCSEFileName}"' } } - } - extensionCustomScriptConfig: { - enabled: true - fileData: [ - { - storageAccountId: nestedDependencies.outputs.storageAccountResourceId - uri: nestedDependencies.outputs.storageAccountCSEFileUrl + extensionDependencyAgentConfig: { + enabled: true + } + extensionAzureDiskEncryptionConfig: { + enabled: true + settings: { + EncryptionOperation: 'EnableEncryption' + KekVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + KeyEncryptionAlgorithm: 'RSA-OAEP' + KeyEncryptionKeyURL: nestedDependencies.outputs.keyVaultEncryptionKeyUrl + KeyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + KeyVaultURL: nestedDependencies.outputs.keyVaultUrl + ResizeOSDisk: 'false' + VolumeType: 'All' } - ] - protectedSettings: { - commandToExecute: 'powershell -ExecutionPolicy Unrestricted -Command "& ./${nestedDependencies.outputs.storageAccountCSEFileName}"' } - } - extensionDependencyAgentConfig: { - enabled: true - } - extensionAzureDiskEncryptionConfig: { - enabled: true - settings: { - EncryptionOperation: 'EnableEncryption' - KekVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - KeyEncryptionAlgorithm: 'RSA-OAEP' - KeyEncryptionKeyURL: nestedDependencies.outputs.keyVaultEncryptionKeyUrl - KeyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - KeyVaultURL: nestedDependencies.outputs.keyVaultUrl - ResizeOSDisk: 'false' - VolumeType: 'All' + extensionDSCConfig: { + enabled: true } - } - extensionDSCConfig: { - enabled: true - } - extensionMonitoringAgentConfig: { - enabled: true - } - extensionNetworkWatcherAgentConfig: { - enabled: true - } - nicConfigurations: [ - { - ipConfigurations: [ - { - name: 'ipconfig1' - properties: { - subnet: { - id: nestedDependencies.outputs.subnetResourceId + extensionMonitoringAgentConfig: { + enabled: true + } + extensionNetworkWatcherAgentConfig: { + enabled: true + } + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig1' + properties: { + subnet: { + id: nestedDependencies.outputs.subnetResourceId + } } } - } + ] + nicSuffix: '-nic01' + } + ] + skuCapacity: 1 + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId ] - nicSuffix: '-nic01' } - ] - skuCapacity: 1 - managedIdentities: { - systemAssigned: true - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - upgradePolicyMode: 'Manual' - vmNamePrefix: 'vmsswinvm' - vmPriority: 'Regular' - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + upgradePolicyMode: 'Manual' + vmNamePrefix: 'vmsswinvm' + vmPriority: 'Regular' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } } -}] +] diff --git a/avm/res/consumption/budget/main.bicep b/avm/res/consumption/budget/main.bicep index 00fd7b662b..d5558266d9 100644 --- a/avm/res/consumption/budget/main.bicep +++ b/avm/res/consumption/budget/main.bicep @@ -80,36 +80,39 @@ param enableTelemetry bool = true @description('Optional. Location deployment metadata.') param location string = deployment().location -var notificationsArray = [for threshold in thresholds: { - 'Actual_GreaterThan_${threshold}_Percentage': { - enabled: true - operator: operator - threshold: threshold - contactEmails: contactEmails - contactRoles: contactRoles - contactGroups: actionGroups - thresholdType: thresholdType +var notificationsArray = [ + for threshold in thresholds: { + 'Actual_GreaterThan_${threshold}_Percentage': { + enabled: true + operator: operator + threshold: threshold + contactEmails: contactEmails + contactRoles: contactRoles + contactGroups: actionGroups + thresholdType: thresholdType + } } -}] +] -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.consumption-budget.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - location: location - 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' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.consumption-budget.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + location: location + 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' + } } } } } -} resource budget 'Microsoft.Consumption/budgets@2023-11-01' = { name: name @@ -121,13 +124,15 @@ resource budget 'Microsoft.Consumption/budgets@2023-11-01' = { startDate: startDate endDate: endDate } - filter: filter ?? (!empty(resourceGroupFilter) ? { - dimensions: { - name: 'ResourceGroupName' - operator: 'In' - values: resourceGroupFilter - } - } : {}) + filter: filter ?? (!empty(resourceGroupFilter) + ? { + dimensions: { + name: 'ResourceGroupName' + operator: 'In' + values: resourceGroupFilter + } + } + : {}) notifications: json(replace(replace(replace(string(notificationsArray), '[{', '{'), '}]', '}'), '}},{', '},')) } } diff --git a/avm/res/consumption/budget/main.json b/avm/res/consumption/budget/main.json index ca59c5284d..13b0e199e7 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.25.53.49325", - "templateHash": "4486017492010556264" + "version": "0.26.54.24096", + "templateHash": "9911588770976622603" }, "name": "Consumption Budgets", "description": "This module deploys a Consumption Budget for Subscriptions.", diff --git a/avm/res/consumption/budget/tests/e2e/defaults/main.test.bicep b/avm/res/consumption/budget/tests/e2e/defaults/main.test.bicep index 4b3537ec84..403a99c156 100644 --- a/avm/res/consumption/budget/tests/e2e/defaults/main.test.bicep +++ b/avm/res/consumption/budget/tests/e2e/defaults/main.test.bicep @@ -21,14 +21,16 @@ param namePrefix string = '#_namePrefix_#' // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - name: '${uniqueString(deployment().name)}-test-${serviceShort}-${iteration}' - params: { - name: '${namePrefix}${serviceShort}001' - location: resourceLocation - amount: 500 - contactEmails: [ - 'dummy@contoso.com' - ] +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + name: '${uniqueString(deployment().name)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: resourceLocation + amount: 500 + contactEmails: [ + 'dummy@contoso.com' + ] + } } -}] +] diff --git a/avm/res/consumption/budget/tests/e2e/max/main.test.bicep b/avm/res/consumption/budget/tests/e2e/max/main.test.bicep index e581db3199..778c4ff7bb 100644 --- a/avm/res/consumption/budget/tests/e2e/max/main.test.bicep +++ b/avm/res/consumption/budget/tests/e2e/max/main.test.bicep @@ -21,25 +21,27 @@ param namePrefix string = '#_namePrefix_#' // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - name: '${uniqueString(deployment().name)}-test-${serviceShort}-${iteration}' - params: { - name: '${namePrefix}${serviceShort}001' - location: resourceLocation - amount: 500 - contactEmails: [ - 'dummy@contoso.com' - ] - resourceGroupFilter: [ - 'rg-group1' - 'rg-group2' - ] - thresholds: [ - 50 - 75 - 90 - 100 - 110 - ] +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + name: '${uniqueString(deployment().name)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: resourceLocation + amount: 500 + contactEmails: [ + 'dummy@contoso.com' + ] + resourceGroupFilter: [ + 'rg-group1' + 'rg-group2' + ] + thresholds: [ + 50 + 75 + 90 + 100 + 110 + ] + } } -}] +] diff --git a/avm/res/consumption/budget/tests/e2e/waf-aligned/main.test.bicep b/avm/res/consumption/budget/tests/e2e/waf-aligned/main.test.bicep index 329c4ea51a..81c8db287d 100644 --- a/avm/res/consumption/budget/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/consumption/budget/tests/e2e/waf-aligned/main.test.bicep @@ -21,21 +21,23 @@ param namePrefix string = '#_namePrefix_#' // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - name: '${uniqueString(deployment().name)}-test-${serviceShort}-${iteration}' - params: { - name: '${namePrefix}${serviceShort}001' - location: resourceLocation - amount: 500 - contactEmails: [ - 'dummy@contoso.com' - ] - thresholds: [ - 50 - 75 - 90 - 100 - 110 - ] +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + name: '${uniqueString(deployment().name)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: resourceLocation + amount: 500 + contactEmails: [ + 'dummy@contoso.com' + ] + thresholds: [ + 50 + 75 + 90 + 100 + 110 + ] + } } -}] +] diff --git a/avm/res/container-registry/registry/cache-rules/main.json b/avm/res/container-registry/registry/cache-rules/main.json index 52b54dce7e..426616994e 100644 --- a/avm/res/container-registry/registry/cache-rules/main.json +++ b/avm/res/container-registry/registry/cache-rules/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "6942960102258463312" + "version": "0.26.54.24096", + "templateHash": "17108035841365544326" }, "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)).", diff --git a/avm/res/container-registry/registry/main.bicep b/avm/res/container-registry/registry/main.bicep index 05bd6d96d4..126074e066 100644 --- a/avm/res/container-registry/registry/main.bicep +++ b/avm/res/container-registry/registry/main.bicep @@ -139,58 +139,91 @@ param customerManagedKey customerManagedKeyType @description('Optional. Array of Cache Rules. Note: This is a preview feature ([ref](https://learn.microsoft.com/en-us/azure/container-registry/tutorial-registry-cache#cache-for-acr-preview)).') param cacheRules array? -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 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 builtInRoleNames = { AcrDelete: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c2f4ef07-c644-48eb-af81-4b1b4947fb11') - AcrImageSigner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6cef56e8-d556-48e5-a04f-b8e64114680f') + AcrImageSigner: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '6cef56e8-d556-48e5-a04f-b8e64114680f' + ) AcrPull: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') AcrPush: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8311e382-0749-4cb8-b61a-304f252e45ec') - AcrQuarantineReader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cdda3590-29a3-44f6-95f2-9f980659eb04') - AcrQuarantineWriter: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c8d4ff99-41c3-41a8-9f60-21dfdad59608') + AcrQuarantineReader: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'cdda3590-29a3-44f6-95f2-9f980659eb04' + ) + AcrQuarantineWriter: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'c8d4ff99-41c3-41a8-9f60-21dfdad59608' + ) 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.containerregistry-registry.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.containerregistry-registry.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} -resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId)) { - name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) - scope: resourceGroup(split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4]) - - resource cMKKey 'keys@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { - name: customerManagedKey.?keyName ?? 'dummyKey' +resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = + if (!empty(customerManagedKey.?keyVaultResourceId)) { + name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) + scope: resourceGroup( + split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], + split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4] + ) + + resource cMKKey 'keys@2023-02-01' existing = + if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { + name: customerManagedKey.?keyName ?? 'dummyKey' + } } -} -resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { - name: last(split(customerManagedKey.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) - scope: resourceGroup(split((customerManagedKey.?userAssignedIdentityResourceId ?? '//'), '/')[2], split((customerManagedKey.?userAssignedIdentityResourceId ?? '////'), '/')[4]) -} +resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = + if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { + name: last(split(customerManagedKey.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) + scope: resourceGroup( + split((customerManagedKey.?userAssignedIdentityResourceId ?? '//'), '/')[2], + split((customerManagedKey.?userAssignedIdentityResourceId ?? '////'), '/')[4] + ) + } resource registry 'Microsoft.ContainerRegistry/registries@2023-06-01-preview' = { name: name @@ -203,20 +236,28 @@ resource registry 'Microsoft.ContainerRegistry/registries@2023-06-01-preview' = properties: { anonymousPullEnabled: anonymousPullEnabled adminUserEnabled: acrAdminUserEnabled - encryption: !empty(customerManagedKey) ? { - status: 'enabled' - keyVaultProperties: { - identity: !empty(customerManagedKey.?userAssignedIdentityResourceId ?? '') ? cMKUserAssignedIdentity.properties.clientId : null - keyIdentifier: !empty(customerManagedKey.?keyVersion ?? '') ? '${cMKKeyVault::cMKKey.properties.keyUri}/${customerManagedKey!.keyVersion}' : cMKKeyVault::cMKKey.properties.keyUriWithVersion - } - } : null + encryption: !empty(customerManagedKey) + ? { + status: 'enabled' + keyVaultProperties: { + identity: !empty(customerManagedKey.?userAssignedIdentityResourceId ?? '') + ? cMKUserAssignedIdentity.properties.clientId + : null + keyIdentifier: !empty(customerManagedKey.?keyVersion ?? '') + ? '${cMKKeyVault::cMKKey.properties.keyUri}/${customerManagedKey!.keyVersion}' + : cMKKeyVault::cMKKey.properties.keyUriWithVersion + } + } + : null policies: { azureADAuthenticationAsArmPolicy: { status: azureADAuthenticationAsArmPolicyStatus } - exportPolicy: acrSku == 'Premium' ? { - status: exportPolicyStatus - } : null + exportPolicy: acrSku == 'Premium' + ? { + status: exportPolicyStatus + } + : null quarantinePolicy: { status: quarantinePolicyStatus } @@ -224,157 +265,192 @@ resource registry 'Microsoft.ContainerRegistry/registries@2023-06-01-preview' = type: 'Notary' status: trustPolicyStatus } - retentionPolicy: acrSku == 'Premium' ? { - days: retentionPolicyDays - status: retentionPolicyStatus - } : null + retentionPolicy: acrSku == 'Premium' + ? { + days: retentionPolicyDays + status: retentionPolicyStatus + } + : null softDeletePolicy: { retentionDays: softDeletePolicyDays status: softDeletePolicyStatus } } dataEndpointEnabled: dataEndpointEnabled - publicNetworkAccess: !empty(publicNetworkAccess) ? any(publicNetworkAccess) : (!empty(privateEndpoints) && empty(networkRuleSetIpRules) ? 'Disabled' : null) + publicNetworkAccess: !empty(publicNetworkAccess) + ? any(publicNetworkAccess) + : (!empty(privateEndpoints) && empty(networkRuleSetIpRules) ? 'Disabled' : null) networkRuleBypassOptions: networkRuleBypassOptions - networkRuleSet: !empty(networkRuleSetIpRules) ? { - defaultAction: networkRuleSetDefaultAction - ipRules: networkRuleSetIpRules - } : null + networkRuleSet: !empty(networkRuleSetIpRules) + ? { + defaultAction: networkRuleSetDefaultAction + ipRules: networkRuleSetIpRules + } + : null zoneRedundancy: acrSku == 'Premium' ? zoneRedundancy : null } } -module registry_replications 'replication/main.bicep' = [for (replication, index) in (replications ?? []): { - name: '${uniqueString(deployment().name, location)}-Registry-Replication-${index}' - params: { - name: replication.name - registryName: registry.name - location: replication.location - regionEndpointEnabled: replication.?regionEndpointEnabled - zoneRedundancy: replication.?zoneRedundancy - tags: replication.?tags ?? tags +module registry_replications 'replication/main.bicep' = [ + for (replication, index) in (replications ?? []): { + name: '${uniqueString(deployment().name, location)}-Registry-Replication-${index}' + params: { + name: replication.name + registryName: registry.name + location: replication.location + regionEndpointEnabled: replication.?regionEndpointEnabled + zoneRedundancy: replication.?zoneRedundancy + tags: replication.?tags ?? tags + } } -}] - -module registry_cacheRules 'cache-rules/main.bicep' = [for (cacheRule, index) in (cacheRules ?? []): { - name: '${uniqueString(deployment().name, location)}-Registry-Cache-${index}' - params: { - registryName: registry.name - sourceRepository: cacheRule.sourceRepository - name: cacheRule.?name ?? replace(replace(cacheRule.sourceRepository, '/', '-'), '.', '-') - targetRepository: cacheRule.?targetRepository ?? cacheRule.sourceRepository - credentialSetResourceId: cacheRule.?credentialSetResourceId +] + +module registry_cacheRules 'cache-rules/main.bicep' = [ + for (cacheRule, index) in (cacheRules ?? []): { + name: '${uniqueString(deployment().name, location)}-Registry-Cache-${index}' + params: { + registryName: registry.name + sourceRepository: cacheRule.sourceRepository + name: cacheRule.?name ?? replace(replace(cacheRule.sourceRepository, '/', '-'), '.', '-') + targetRepository: cacheRule.?targetRepository ?? cacheRule.sourceRepository + credentialSetResourceId: cacheRule.?credentialSetResourceId + } } -}] - -module registry_webhooks 'webhook/main.bicep' = [for (webhook, index) in (webhooks ?? []): { - name: '${uniqueString(deployment().name, location)}-Registry-Webhook-${index}' - params: { - name: webhook.name - registryName: registry.name - location: webhook.?location ?? location - action: webhook.?action ?? [ - 'chart_delete' - 'chart_push' - 'delete' - 'push' - 'quarantine' - ] - customHeaders: webhook.?customHeaders - scope: webhook.?scope - status: webhook.?status - serviceUri: webhook.serviceUri - tags: webhook.?tags ?? tags +] + +module registry_webhooks 'webhook/main.bicep' = [ + for (webhook, index) in (webhooks ?? []): { + name: '${uniqueString(deployment().name, location)}-Registry-Webhook-${index}' + params: { + name: webhook.name + registryName: registry.name + location: webhook.?location ?? location + action: webhook.?action ?? [ + 'chart_delete' + 'chart_push' + 'delete' + 'push' + 'quarantine' + ] + customHeaders: webhook.?customHeaders + scope: webhook.?scope + status: webhook.?status + serviceUri: webhook.serviceUri + tags: webhook.?tags ?? tags + } } -}] +] -resource registry_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.' +resource registry_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: registry } - scope: registry -} -resource registry_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource registry_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: registry } - scope: registry -}] +] -resource registry_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(registry.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource registry_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(registry.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: registry } - scope: registry -}] - -module registry_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-registry-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(registry.id, '/'))}-${privateEndpoint.?service ?? 'registry'}-${index}' - privateLinkServiceConnections: [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(registry.id, '/'))}-${privateEndpoint.?service ?? 'registry'}-${index}' - properties: { - privateLinkServiceId: registry.id - groupIds: [ - privateEndpoint.?service ?? 'registry' - ] +] + +module registry_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-registry-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(registry.id, '/'))}-${privateEndpoint.?service ?? 'registry'}-${index}' + privateLinkServiceConnections: [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(registry.id, '/'))}-${privateEndpoint.?service ?? 'registry'}-${index}' + properties: { + privateLinkServiceId: registry.id + groupIds: [ + privateEndpoint.?service ?? 'registry' + ] + } } - } - ] - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(registry.id, '/'))}-${privateEndpoint.?service ?? 'registry'}-${index}' - properties: { - privateLinkServiceId: registry.id - groupIds: [ - privateEndpoint.?service ?? 'registry' + ] + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(registry.id, '/'))}-${privateEndpoint.?service ?? 'registry'}-${index}' + properties: { + privateLinkServiceId: registry.id + groupIds: [ + privateEndpoint.?service ?? 'registry' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] +] @description('The Name of the Azure container registry.') output name string = registry.name diff --git a/avm/res/container-registry/registry/main.json b/avm/res/container-registry/registry/main.json index e08259390f..b176210972 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.25.53.49325", - "templateHash": "9195818754355186204" + "version": "0.26.54.24096", + "templateHash": "15445287807627348186" }, "name": "Azure Container Registries (ACR)", "description": "This module deploys an Azure Container Registry (ACR).", @@ -943,8 +943,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "10714256463183699741" + "version": "0.26.54.24096", + "templateHash": "16451316437757175736" }, "name": "Azure Container Registry (ACR) Replications", "description": "This module deploys an Azure Container Registry (ACR) Replication.", @@ -1091,8 +1091,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "6942960102258463312" + "version": "0.26.54.24096", + "templateHash": "17108035841365544326" }, "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)).", @@ -1232,8 +1232,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3986666280667981658" + "version": "0.26.54.24096", + "templateHash": "10731035117081750792" }, "name": "Azure Container Registry (ACR) Webhooks", "description": "This module deploys an Azure Container Registry (ACR) Webhook.", diff --git a/avm/res/container-registry/registry/replication/main.json b/avm/res/container-registry/registry/replication/main.json index ea887b53b1..61c5d1a182 100644 --- a/avm/res/container-registry/registry/replication/main.json +++ b/avm/res/container-registry/registry/replication/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "10714256463183699741" + "version": "0.26.54.24096", + "templateHash": "16451316437757175736" }, "name": "Azure Container Registry (ACR) Replications", "description": "This module deploys an Azure Container Registry (ACR) Replication.", diff --git a/avm/res/container-registry/registry/tests/e2e/defaults/main.test.bicep b/avm/res/container-registry/registry/tests/e2e/defaults/main.test.bicep index c9ee60ee98..4913076429 100644 --- a/avm/res/container-registry/registry/tests/e2e/defaults/main.test.bicep +++ b/avm/res/container-registry/registry/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 +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 + } } -}] +] diff --git a/avm/res/container-registry/registry/tests/e2e/encr/dependencies.bicep b/avm/res/container-registry/registry/tests/e2e/encr/dependencies.bicep index 2a44c0d13c..3d3446c847 100644 --- a/avm/res/container-registry/registry/tests/e2e/encr/dependencies.bicep +++ b/avm/res/container-registry/registry/tests/e2e/encr/dependencies.bicep @@ -69,7 +69,10 @@ resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { properties: { principalId: managedIdentity.properties.principalId // Key Vault Crypto User - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '12338af0-0e69-4776-bea7-57ae8d297424' + ) principalType: 'ServicePrincipal' } } diff --git a/avm/res/container-registry/registry/tests/e2e/encr/main.test.bicep b/avm/res/container-registry/registry/tests/e2e/encr/main.test.bicep index 740e8c19d6..7e947cfc34 100644 --- a/avm/res/container-registry/registry/tests/e2e/encr/main.test.bicep +++ b/avm/res/container-registry/registry/tests/e2e/encr/main.test.bicep @@ -51,26 +51,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 - acrSku: 'Premium' - customerManagedKey: { - keyName: nestedDependencies.outputs.keyVaultEncryptionKeyName - keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - userAssignedIdentityResourceId: nestedDependencies.outputs.managedIdentityResourceId - } - publicNetworkAccess: 'Disabled' - 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 + acrSku: 'Premium' + customerManagedKey: { + keyName: nestedDependencies.outputs.keyVaultEncryptionKeyName + keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + userAssignedIdentityResourceId: nestedDependencies.outputs.managedIdentityResourceId + } + publicNetworkAccess: 'Disabled' + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/container-registry/registry/tests/e2e/max/dependencies.bicep b/avm/res/container-registry/registry/tests/e2e/max/dependencies.bicep index 73256e4598..16d9a64d1b 100644 --- a/avm/res/container-registry/registry/tests/e2e/max/dependencies.bicep +++ b/avm/res/container-registry/registry/tests/e2e/max/dependencies.bicep @@ -57,7 +57,10 @@ 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 + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) // Reader principalType: 'ServicePrincipal' } } diff --git a/avm/res/container-registry/registry/tests/e2e/max/main.test.bicep b/avm/res/container-registry/registry/tests/e2e/max/main.test.bicep index 6153fdefb5..c7b9f5e186 100644 --- a/avm/res/container-registry/registry/tests/e2e/max/main.test.bicep +++ b/avm/res/container-registry/registry/tests/e2e/max/main.test.bicep @@ -62,116 +62,121 @@ 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 - acrAdminUserEnabled: false - acrSku: 'Premium' - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - exportPolicyStatus: 'enabled' - azureADAuthenticationAsArmPolicyStatus: 'enabled' - softDeletePolicyStatus: 'disabled' - softDeletePolicyDays: 7 - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - privateEndpoints: [ - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +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 + acrAdminUserEnabled: false + acrSku: 'Premium' + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } + ] + exportPolicyStatus: 'enabled' + azureADAuthenticationAsArmPolicyStatus: 'enabled' + softDeletePolicyStatus: 'disabled' + softDeletePolicyDays: 7 + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId + privateEndpoints: [ + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + } + ] + networkRuleSetIpRules: [ + { + action: 'Allow' + value: '40.74.28.0/23' + } + ] + quarantinePolicyStatus: 'enabled' + replications: [ + { + location: nestedDependencies.outputs.pairedRegionName + name: nestedDependencies.outputs.pairedRegionName + } + ] + 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' + } + ] + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId ] } - ] - networkRuleSetIpRules: [ - { - action: 'Allow' - value: '40.74.28.0/23' - } - ] - quarantinePolicyStatus: 'enabled' - replications: [ - { - location: nestedDependencies.outputs.pairedRegionName - name: nestedDependencies.outputs.pairedRegionName - } - ] - 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' - } - ] - managedIdentities: { - systemAssigned: true - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId + trustPolicyStatus: 'enabled' + cacheRules: [ + { + name: 'customRule' + sourceRepository: 'docker.io/library/hello-world' + targetRepository: 'cached-docker-hub/hello-world' + } + { + sourceRepository: 'docker.io/library/hello-world' + } ] - } - trustPolicyStatus: 'enabled' - cacheRules: [ - { - name: 'customRule' - sourceRepository: 'docker.io/library/hello-world' - targetRepository: 'cached-docker-hub/hello-world' - } - { - sourceRepository: 'docker.io/library/hello-world' - } - ] - webhooks: [ - { - name: '${namePrefix}acrx001webhook' - serviceUri: 'https://www.contoso.com/webhook' + webhooks: [ + { + name: '${namePrefix}acrx001webhook' + serviceUri: 'https://www.contoso.com/webhook' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/container-registry/registry/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/container-registry/registry/tests/e2e/waf-aligned/dependencies.bicep index 04abeed1bb..0e56a92b7a 100644 --- a/avm/res/container-registry/registry/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/container-registry/registry/tests/e2e/waf-aligned/dependencies.bicep @@ -16,7 +16,10 @@ 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 + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) // Reader principalType: 'ServicePrincipal' } } diff --git a/avm/res/container-registry/registry/tests/e2e/waf-aligned/main.test.bicep b/avm/res/container-registry/registry/tests/e2e/waf-aligned/main.test.bicep index c046264a97..4b99ab2618 100644 --- a/avm/res/container-registry/registry/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/container-registry/registry/tests/e2e/waf-aligned/main.test.bicep @@ -60,42 +60,44 @@ 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 - acrAdminUserEnabled: false - acrSku: 'Premium' - diagnosticSettings: [ - { - 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 + acrAdminUserEnabled: false + acrSku: 'Premium' + diagnosticSettings: [ + { + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + exportPolicyStatus: 'enabled' + azureADAuthenticationAsArmPolicyStatus: 'enabled' + softDeletePolicyStatus: 'disabled' + softDeletePolicyDays: 7 + quarantinePolicyStatus: 'enabled' + replications: [ + { + location: nestedDependencies.outputs.pairedRegionName + name: nestedDependencies.outputs.pairedRegionName + } + ] + trustPolicyStatus: 'enabled' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - exportPolicyStatus: 'enabled' - azureADAuthenticationAsArmPolicyStatus: 'enabled' - softDeletePolicyStatus: 'disabled' - softDeletePolicyDays: 7 - quarantinePolicyStatus: 'enabled' - replications: [ - { - location: nestedDependencies.outputs.pairedRegionName - name: nestedDependencies.outputs.pairedRegionName - } - ] - trustPolicyStatus: 'enabled' - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/container-registry/registry/webhook/main.json b/avm/res/container-registry/registry/webhook/main.json index c5520f2893..4c7f571ed7 100644 --- a/avm/res/container-registry/registry/webhook/main.json +++ b/avm/res/container-registry/registry/webhook/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3986666280667981658" + "version": "0.26.54.24096", + "templateHash": "10731035117081750792" }, "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/agent-pool/main.bicep b/avm/res/container-service/managed-cluster/agent-pool/main.bicep index f34cd88385..d1daa97efe 100644 --- a/avm/res/container-service/managed-cluster/agent-pool/main.bicep +++ b/avm/res/container-service/managed-cluster/agent-pool/main.bicep @@ -156,9 +156,11 @@ resource agentPool 'Microsoft.ContainerService/managedClusters/agentPools@2023-0 properties: { availabilityZones: availabilityZones count: count - creationData: !empty(sourceResourceId) ? { - sourceResourceId: sourceResourceId - } : null + creationData: !empty(sourceResourceId) + ? { + sourceResourceId: sourceResourceId + } + : null enableAutoScaling: enableAutoScaling enableEncryptionAtHost: enableEncryptionAtHost enableFIPS: enableFIPS 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 4238233b6a..f6fc6ebeb9 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.25.53.49325", - "templateHash": "11449186283530676915" + "version": "0.26.54.24096", + "templateHash": "8772299678418708256" }, "name": "Azure Kubernetes Service (AKS) Managed Cluster Agent Pools", "description": "This module deploys an Azure Kubernetes Service (AKS) Managed Cluster Agent Pool.", diff --git a/avm/res/container-service/managed-cluster/main.bicep b/avm/res/container-service/managed-cluster/main.bicep index 29f1e1fea5..99ed22d4c5 100644 --- a/avm/res/container-service/managed-cluster/main.bicep +++ b/avm/res/container-service/managed-cluster/main.bicep @@ -372,65 +372,127 @@ param metricAnnotationsAllowList string = '' // Variables // // =========== // -var formattedUserAssignedIdentities = reduce(map((managedIdentities.?userAssignedResourcesIds ?? []), (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) ? 'SystemAssigned' : (!empty(managedIdentities.?userAssignedResourcesIds ?? {}) ? 'UserAssigned' : null) - userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null -} : null +var formattedUserAssignedIdentities = reduce( + map((managedIdentities.?userAssignedResourcesIds ?? []), (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) + ? 'SystemAssigned' + : (!empty(managedIdentities.?userAssignedResourcesIds ?? {}) ? 'UserAssigned' : null) + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null + } + : null var builtInRoleNames = { - 'Azure Kubernetes Fleet Manager Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '63bb64ad-9799-4770-b5c3-24ed299a07bf') - 'Azure Kubernetes Fleet Manager RBAC Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '434fb43a-c01c-447e-9f67-c3ad923cfaba') - 'Azure Kubernetes Fleet Manager RBAC Cluster Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18ab4d3d-a1bf-4477-8ad9-8359bc988f69') - 'Azure Kubernetes Fleet Manager RBAC Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '30b27cfc-9c84-438e-b0ce-70e35255df80') - 'Azure Kubernetes Fleet Manager RBAC Writer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5af6afb3-c06c-4fa4-8848-71a8aee05683') - 'Azure Kubernetes Service Cluster Admin Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8') - 'Azure Kubernetes Service Cluster Monitoring User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1afdec4b-e479-420e-99e7-f82237c7c5e6') - 'Azure Kubernetes Service Cluster User Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4abbcc35-e782-43d8-92c5-2d3f1bd2253f') - 'Azure Kubernetes Service Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8') - 'Azure Kubernetes Service RBAC Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3498e952-d568-435e-9b2c-8d77e338d7f7') - 'Azure Kubernetes Service RBAC Cluster Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b') - 'Azure Kubernetes Service RBAC Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f6c6a51-bcf8-42ba-9220-52d62157d7db') - 'Azure Kubernetes Service RBAC Writer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb') + 'Azure Kubernetes Fleet Manager Contributor Role': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '63bb64ad-9799-4770-b5c3-24ed299a07bf' + ) + 'Azure Kubernetes Fleet Manager RBAC Admin': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '434fb43a-c01c-447e-9f67-c3ad923cfaba' + ) + 'Azure Kubernetes Fleet Manager RBAC Cluster Admin': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18ab4d3d-a1bf-4477-8ad9-8359bc988f69' + ) + 'Azure Kubernetes Fleet Manager RBAC Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '30b27cfc-9c84-438e-b0ce-70e35255df80' + ) + 'Azure Kubernetes Fleet Manager RBAC Writer': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '5af6afb3-c06c-4fa4-8848-71a8aee05683' + ) + 'Azure Kubernetes Service Cluster Admin Role': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8' + ) + 'Azure Kubernetes Service Cluster Monitoring User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '1afdec4b-e479-420e-99e7-f82237c7c5e6' + ) + 'Azure Kubernetes Service Cluster User Role': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '4abbcc35-e782-43d8-92c5-2d3f1bd2253f' + ) + 'Azure Kubernetes Service Contributor Role': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8' + ) + 'Azure Kubernetes Service RBAC Admin': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '3498e952-d568-435e-9b2c-8d77e338d7f7' + ) + 'Azure Kubernetes Service RBAC Cluster Admin': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b' + ) + 'Azure Kubernetes Service RBAC Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '7f6c6a51-bcf8-42ba-9220-52d62157d7db' + ) + 'Azure Kubernetes Service RBAC Writer': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb' + ) Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Kubernetes Agentless Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a2ae44-610b-4500-93be-660a0c5f5ca6') + 'Kubernetes Agentless Operator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'd5a2ae44-610b-4500-93be-660a0c5f5ca6' + ) 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') + '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' + ) } // ============ // // Dependencies // // ============ // -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.containerservice-managedcluster.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.containerservice-managedcluster.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} -resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId)) { - name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) - scope: resourceGroup(split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4]) - - resource cMKKey 'keys@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { - name: customerManagedKey.?keyName ?? 'dummyKey' +resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = + if (!empty(customerManagedKey.?keyVaultResourceId)) { + name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) + scope: resourceGroup( + split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], + split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4] + ) + + resource cMKKey 'keys@2023-02-01' existing = + if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { + name: customerManagedKey.?keyName ?? 'dummyKey' + } } -} // ============== // // Main Resources // @@ -452,23 +514,27 @@ resource managedCluster 'Microsoft.ContainerService/managedClusters@2023-07-02-p kubernetesVersion: kubernetesVersion dnsPrefix: dnsPrefix agentPoolProfiles: primaryAgentPoolProfile - linuxProfile: !empty(sshPublicKey) ? { - adminUsername: adminUsername - ssh: { - publicKeys: [ - { - keyData: sshPublicKey ?? '' + linuxProfile: !empty(sshPublicKey) + ? { + adminUsername: adminUsername + ssh: { + publicKeys: [ + { + keyData: sshPublicKey ?? '' + } + ] } - ] - } - } : null + } + : null servicePrincipalProfile: aksServicePrincipalProfile ingressProfile: { webAppRouting: { enabled: webApplicationRoutingEnabled - dnsZoneResourceIds: !empty(dnsZoneResourceId) ? [ - any(dnsZoneResourceId) - ] : null + dnsZoneResourceIds: !empty(dnsZoneResourceId) + ? [ + any(dnsZoneResourceId) + ] + : null } } addonProfiles: { @@ -478,26 +544,32 @@ resource managedCluster 'Microsoft.ContainerService/managedClusters@2023-07-02-p ingressApplicationGateway: { enabled: ingressApplicationGatewayEnabled && !empty(appGatewayResourceId) #disable-next-line BCP321 // Value will not be used if null or empty - config: ingressApplicationGatewayEnabled && !empty(appGatewayResourceId) ? { - applicationGatewayId: appGatewayResourceId - effectiveApplicationGatewayId: appGatewayResourceId - } : null + config: ingressApplicationGatewayEnabled && !empty(appGatewayResourceId) + ? { + applicationGatewayId: appGatewayResourceId + effectiveApplicationGatewayId: appGatewayResourceId + } + : null } omsagent: { enabled: omsAgentEnabled && !empty(monitoringWorkspaceId) #disable-next-line BCP321 // Value will not be used if null or empty - config: omsAgentEnabled && !empty(monitoringWorkspaceId) ? { - logAnalyticsWorkspaceResourceID: monitoringWorkspaceId - } : null + config: omsAgentEnabled && !empty(monitoringWorkspaceId) + ? { + logAnalyticsWorkspaceResourceID: monitoringWorkspaceId + } + : null } aciConnectorLinux: { enabled: aciConnectorLinuxEnabled } azurepolicy: { enabled: azurePolicyEnabled - config: azurePolicyEnabled ? { - version: azurePolicyVersion - } : null + config: azurePolicyEnabled + ? { + version: azurePolicyVersion + } + : null } openServiceMesh: { enabled: openServiceMeshEnabled @@ -508,14 +580,18 @@ resource managedCluster 'Microsoft.ContainerService/managedClusters@2023-07-02-p } azureKeyvaultSecretsProvider: { enabled: enableKeyvaultSecretsProvider - config: enableKeyvaultSecretsProvider ? { - enableSecretRotation: enableSecretRotation - } : null + config: enableKeyvaultSecretsProvider + ? { + enableSecretRotation: enableSecretRotation + } + : null } } - oidcIssuerProfile: enableOidcIssuerProfile ? { - enabled: enableOidcIssuerProfile - } : null + oidcIssuerProfile: enableOidcIssuerProfile + ? { + enabled: enableOidcIssuerProfile + } + : null enableRBAC: enableRBAC disableLocalAccounts: disableLocalAccounts nodeResourceGroup: nodeResourceGroup @@ -530,12 +606,14 @@ resource managedCluster 'Microsoft.ContainerService/managedClusters@2023-07-02-p dnsServiceIP: dnsServiceIP outboundType: outboundType loadBalancerSku: loadBalancerSku - loadBalancerProfile: managedOutboundIPCount != 0 ? { - managedOutboundIPs: { - count: managedOutboundIPCount - } - effectiveOutboundIPs: [] - } : null + loadBalancerProfile: managedOutboundIPCount != 0 + ? { + managedOutboundIPs: { + count: managedOutboundIPCount + } + effectiveOutboundIPs: [] + } + : null } aadProfile: { clientAppID: aadProfileClientAppID @@ -576,28 +654,32 @@ resource managedCluster 'Microsoft.ContainerService/managedClusters@2023-07-02-p privateDNSZone: privateDNSZone } azureMonitorProfile: { - logs: enableAzureMonitorProfileLogs ? { - appMonitoring: { - enabled: enableAppMonitoring - } - containerInsights: { - enabled: enableContainerInsights - logAnalyticsWorkspaceResourceId: !empty(monitoringWorkspaceId) ? monitoringWorkspaceId : null - windowsHostLogs: { - enabled: enableWindowsHostLogs + logs: enableAzureMonitorProfileLogs + ? { + appMonitoring: { + enabled: enableAppMonitoring + } + containerInsights: { + enabled: enableContainerInsights + logAnalyticsWorkspaceResourceId: !empty(monitoringWorkspaceId) ? monitoringWorkspaceId : null + windowsHostLogs: { + enabled: enableWindowsHostLogs + } + } } - } - } : null - metrics: enableAzureMonitorProfileMetrics ? { - enabled: enableAzureMonitorProfileMetrics - appMonitoringOpenTelemetryMetrics: { - enabled: enableAppMonitoringOpenTelemetryMetrics - } - kubeStateMetrics: { - metricLabelsAllowlist: metricLabelsAllowlist - metricAnnotationsAllowList: metricAnnotationsAllowList - } - } : null + : null + metrics: enableAzureMonitorProfileMetrics + ? { + enabled: enableAzureMonitorProfileMetrics + appMonitoringOpenTelemetryMetrics: { + enabled: enableAppMonitoringOpenTelemetryMetrics + } + kubeStateMetrics: { + metricLabelsAllowlist: metricLabelsAllowlist + metricAnnotationsAllowList: metricAnnotationsAllowList + } + } + : null } podIdentityProfile: { allowNetworkPluginKubenet: podIdentityProfileAllowNetworkPluginKubenet @@ -606,15 +688,19 @@ resource managedCluster 'Microsoft.ContainerService/managedClusters@2023-07-02-p userAssignedIdentityExceptions: podIdentityProfileUserAssignedIdentityExceptions } securityProfile: { - defender: enableAzureDefender ? { - securityMonitoring: { - enabled: enableAzureDefender - } - logAnalyticsWorkspaceResourceId: monitoringWorkspaceId - } : null - workloadIdentity: enableWorkloadIdentity ? { - enabled: enableWorkloadIdentity - } : null + defender: enableAzureDefender + ? { + securityMonitoring: { + enabled: enableAzureDefender + } + logAnalyticsWorkspaceResourceId: monitoringWorkspaceId + } + : null + workloadIdentity: enableWorkloadIdentity + ? { + enabled: enableWorkloadIdentity + } + : null } storageProfile: { blobCSIDriver: { @@ -634,124 +720,151 @@ resource managedCluster 'Microsoft.ContainerService/managedClusters@2023-07-02-p } } -module managedCluster_agentPools 'agent-pool/main.bicep' = [for (agentPool, index) in (agentPools ?? []): { - name: '${uniqueString(deployment().name, location)}-ManagedCluster-AgentPool-${index}' - params: { - managedClusterName: managedCluster.?name - name: agentPool.name - availabilityZones: agentPool.?availabilityZones - count: agentPool.?count - sourceResourceId: agentPool.?sourceResourceId - enableAutoScaling: agentPool.?enableAutoScaling - enableEncryptionAtHost: agentPool.?enableEncryptionAtHost - enableFIPS: agentPool.?enableFIPS - enableNodePublicIP: agentPool.?enableNodePublicIP - enableUltraSSD: agentPool.?enableUltraSSD - gpuInstanceProfile: agentPool.?gpuInstanceProfile - kubeletDiskType: agentPool.?kubeletDiskType - maxCount: agentPool.?maxCount - maxPods: agentPool.?maxPods - minCount: agentPool.?minCount - mode: agentPool.?mode - nodeLabels: agentPool.?nodeLabels - nodePublicIpPrefixId: agentPool.?nodePublicIpPrefixId - nodeTaints: agentPool.?nodeTaints - orchestratorVersion: agentPool.?orchestratorVersion ?? kubernetesVersion - osDiskSizeGB: agentPool.?osDiskSizeGB - osDiskType: agentPool.?osDiskType - osSku: agentPool.?osSku - osType: agentPool.?osType - podSubnetId: agentPool.?podSubnetId - proximityPlacementGroupResourceId: agentPool.?proximityPlacementGroupResourceId - scaleDownMode: agentPool.?scaleDownMode - scaleSetEvictionPolicy: agentPool.?scaleSetEvictionPolicy - scaleSetPriority: agentPool.?scaleSetPriority - spotMaxPrice: agentPool.?spotMaxPrice - tags: agentPool.?tags ?? tags - type: agentPool.?type - maxSurge: agentPool.?maxSurge - vmSize: agentPool.?vmSize - vnetSubnetId: agentPool.?vnetSubnetId - workloadRuntime: agentPool.?workloadRuntime +module managedCluster_agentPools 'agent-pool/main.bicep' = [ + for (agentPool, index) in (agentPools ?? []): { + name: '${uniqueString(deployment().name, location)}-ManagedCluster-AgentPool-${index}' + params: { + managedClusterName: managedCluster.?name + name: agentPool.name + availabilityZones: agentPool.?availabilityZones + count: agentPool.?count + sourceResourceId: agentPool.?sourceResourceId + enableAutoScaling: agentPool.?enableAutoScaling + enableEncryptionAtHost: agentPool.?enableEncryptionAtHost + enableFIPS: agentPool.?enableFIPS + enableNodePublicIP: agentPool.?enableNodePublicIP + enableUltraSSD: agentPool.?enableUltraSSD + gpuInstanceProfile: agentPool.?gpuInstanceProfile + kubeletDiskType: agentPool.?kubeletDiskType + maxCount: agentPool.?maxCount + maxPods: agentPool.?maxPods + minCount: agentPool.?minCount + mode: agentPool.?mode + nodeLabels: agentPool.?nodeLabels + nodePublicIpPrefixId: agentPool.?nodePublicIpPrefixId + nodeTaints: agentPool.?nodeTaints + orchestratorVersion: agentPool.?orchestratorVersion ?? kubernetesVersion + osDiskSizeGB: agentPool.?osDiskSizeGB + osDiskType: agentPool.?osDiskType + osSku: agentPool.?osSku + osType: agentPool.?osType + podSubnetId: agentPool.?podSubnetId + proximityPlacementGroupResourceId: agentPool.?proximityPlacementGroupResourceId + scaleDownMode: agentPool.?scaleDownMode + scaleSetEvictionPolicy: agentPool.?scaleSetEvictionPolicy + scaleSetPriority: agentPool.?scaleSetPriority + spotMaxPrice: agentPool.?spotMaxPrice + tags: agentPool.?tags ?? tags + type: agentPool.?type + maxSurge: agentPool.?maxSurge + vmSize: agentPool.?vmSize + vnetSubnetId: agentPool.?vnetSubnetId + workloadRuntime: agentPool.?workloadRuntime + } } -}] - -module managedCluster_extension 'br/public:avm/res/kubernetes-configuration/extension:0.2.0' = if (!empty(fluxExtension)) { - name: '${uniqueString(deployment().name, location)}-ManagedCluster-FluxExtension' - params: { - clusterName: managedCluster.name - configurationProtectedSettings: fluxExtension.?configurationProtectedSettings - configurationSettings: fluxExtension.?configurationSettings - enableTelemetry: enableTelemetry - extensionType: 'microsoft.flux' - fluxConfigurations: fluxExtension.?configurations - location: location - name: 'flux' - releaseNamespace: fluxExtension.?releaseNamespace ?? 'flux-system' - releaseTrain: fluxExtension.?releaseTrain ?? 'Stable' - version: fluxExtension.?version +] + +module managedCluster_extension 'br/public:avm/res/kubernetes-configuration/extension:0.2.0' = + if (!empty(fluxExtension)) { + name: '${uniqueString(deployment().name, location)}-ManagedCluster-FluxExtension' + params: { + clusterName: managedCluster.name + configurationProtectedSettings: fluxExtension.?configurationProtectedSettings + configurationSettings: fluxExtension.?configurationSettings + enableTelemetry: enableTelemetry + extensionType: 'microsoft.flux' + fluxConfigurations: fluxExtension.?configurations + location: location + name: 'flux' + releaseNamespace: fluxExtension.?releaseNamespace ?? 'flux-system' + releaseTrain: fluxExtension.?releaseTrain ?? 'Stable' + version: fluxExtension.?version + } } -} -resource managedCluster_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.' +resource managedCluster_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: managedCluster } - scope: managedCluster -} -resource managedCluster_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource managedCluster_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: managedCluster } - scope: managedCluster -}] - -resource managedCluster_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(managedCluster.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +] + +resource managedCluster_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(managedCluster.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: managedCluster } - scope: managedCluster -}] +] -resource dnsZone 'Microsoft.Network/dnsZones@2018-05-01' existing = if (enableDnsZoneContributorRoleAssignment == true && dnsZoneResourceId != null && webApplicationRoutingEnabled) { - name: last(split((!empty(dnsZoneResourceId) ? any(dnsZoneResourceId) : '/dummmyZone'), '/'))! -} +resource dnsZone 'Microsoft.Network/dnsZones@2018-05-01' existing = + if (enableDnsZoneContributorRoleAssignment == true && dnsZoneResourceId != null && webApplicationRoutingEnabled) { + name: last(split((!empty(dnsZoneResourceId) ? any(dnsZoneResourceId) : '/dummmyZone'), '/'))! + } -resource dnsZone_roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (enableDnsZoneContributorRoleAssignment == true && dnsZoneResourceId != null && webApplicationRoutingEnabled) { - name: guid(dnsZone.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314'), 'DNS Zone Contributor') - properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314') // 'DNS Zone Contributor' - principalId: managedCluster.properties.ingressProfile.webAppRouting.identity.objectId - principalType: 'ServicePrincipal' +resource dnsZone_roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = + if (enableDnsZoneContributorRoleAssignment == true && dnsZoneResourceId != null && webApplicationRoutingEnabled) { + name: guid( + dnsZone.id, + subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314'), + 'DNS Zone Contributor' + ) + properties: { + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'befefa01-2a29-4197-83a8-272ff33ce314' + ) // 'DNS Zone Contributor' + principalId: managedCluster.properties.ingressProfile.webAppRouting.identity.objectId + principalType: 'ServicePrincipal' + } + scope: dnsZone } - scope: dnsZone -} @description('The resource ID of the managed cluster.') output resourceId string = managedCluster.id @@ -763,7 +876,9 @@ output resourceGroupName string = resourceGroup().name output name string = managedCluster.name @description('The control plane FQDN of the managed cluster.') -output controlPlaneFQDN string = enablePrivateCluster ? managedCluster.properties.privateFQDN : managedCluster.properties.fqdn +output controlPlaneFQDN string = enablePrivateCluster + ? managedCluster.properties.privateFQDN + : managedCluster.properties.fqdn @description('The principal ID of the system assigned identity.') output systemAssignedMIPrincipalId string = managedCluster.?identity.?principalId ?? '' diff --git a/avm/res/container-service/managed-cluster/main.json b/avm/res/container-service/managed-cluster/main.json index c5098ced93..38965b9632 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.25.53.49325", - "templateHash": "15404583857670962921" + "version": "0.26.54.24096", + "templateHash": "1556415774507310743" }, "name": "Azure Kubernetes Service (AKS) Managed Clusters", "description": "This module deploys an Azure Kubernetes Service (AKS) Managed Cluster.", @@ -1862,8 +1862,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11449186283530676915" + "version": "0.26.54.24096", + "templateHash": "8772299678418708256" }, "name": "Azure Kubernetes Service (AKS) Managed Cluster Agent Pools", "description": "This module deploys an Azure Kubernetes Service (AKS) Managed Cluster Agent Pool.", diff --git a/avm/res/container-service/managed-cluster/tests/e2e/azure/dependencies.bicep b/avm/res/container-service/managed-cluster/tests/e2e/azure/dependencies.bicep index 813a8a74ba..e2274a7fbb 100644 --- a/avm/res/container-service/managed-cluster/tests/e2e/azure/dependencies.bicep +++ b/avm/res/container-service/managed-cluster/tests/e2e/azure/dependencies.bicep @@ -36,12 +36,15 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { addressPrefix ] } - subnets: map(range(0, 3), i => { + subnets: map( + range(0, 3), + i => { name: 'subnet-${i}' properties: { addressPrefix: cidrSubnet(addressPrefix, 24, i) } - }) + } + ) } } @@ -93,7 +96,10 @@ resource keyPermissionsKeyVaultCryptoUser 'Microsoft.Authorization/roleAssignmen scope: keyVault properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // KeyVault-Crypto-User + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '12338af0-0e69-4776-bea7-57ae8d297424' + ) // KeyVault-Crypto-User principalType: 'ServicePrincipal' } } @@ -148,7 +154,10 @@ resource roleAssignmentKubeletIdentity 'Microsoft.Authorization/roleAssignments@ scope: managedIdentityKubeletIdentity properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830') // Managed Identity Operator Role used for Kubelet identity. + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f1a07417-d97a-45cb-824c-7a7467783830' + ) // Managed Identity Operator Role used for Kubelet identity. principalType: 'ServicePrincipal' } } diff --git a/avm/res/container-service/managed-cluster/tests/e2e/azure/main.test.bicep b/avm/res/container-service/managed-cluster/tests/e2e/azure/main.test.bicep index a2ee31ff00..618c2153ac 100644 --- a/avm/res/container-service/managed-cluster/tests/e2e/azure/main.test.bicep +++ b/avm/res/container-service/managed-cluster/tests/e2e/azure/main.test.bicep @@ -69,217 +69,222 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - primaryAgentPoolProfile: [ - { - availabilityZones: [ - '3' - ] - count: 1 - enableAutoScaling: true - maxCount: 3 - maxPods: 30 - minCount: 1 - mode: 'System' - name: 'systempool' - osDiskSizeGB: 0 - osType: 'Linux' - serviceCidr: '' - type: 'VirtualMachineScaleSets' - vmSize: 'Standard_DS2_v2' - vnetSubnetID: nestedDependencies.outputs.subnetResourceIds[0] - } - ] - agentPools: [ - { - availabilityZones: [ - '3' - ] - count: 2 - enableAutoScaling: true - maxCount: 3 - maxPods: 30 - minCount: 1 - minPods: 2 - mode: 'User' - name: 'userpool1' - nodeLabels: {} - nodeTaints: [ - 'CriticalAddonsOnly=true:NoSchedule' - ] - osDiskSizeGB: 128 - osType: 'Linux' - scaleSetEvictionPolicy: 'Delete' - scaleSetPriority: 'Regular' - type: 'VirtualMachineScaleSets' - vmSize: 'Standard_DS2_v2' - vnetSubnetID: nestedDependencies.outputs.subnetResourceIds[1] - proximityPlacementGroupResourceId: nestedDependencies.outputs.proximityPlacementGroupResourceId - } - { - availabilityZones: [ - '3' - ] - count: 2 - enableAutoScaling: true - maxCount: 3 - maxPods: 30 - minCount: 1 - minPods: 2 - mode: 'User' - name: 'userpool2' - nodeLabels: {} - nodeTaints: [ - 'CriticalAddonsOnly=true:NoSchedule' - ] - osDiskSizeGB: 128 - osType: 'Linux' - scaleSetEvictionPolicy: 'Delete' - scaleSetPriority: 'Regular' - type: 'VirtualMachineScaleSets' - vmSize: 'Standard_DS2_v2' - vnetSubnetID: nestedDependencies.outputs.subnetResourceIds[2] - } - ] - autoUpgradeProfileUpgradeChannel: 'stable' - enableWorkloadIdentity: true - enableOidcIssuerProfile: true - networkPlugin: 'azure' - networkDataplane: 'azure' - networkPluginMode: 'overlay' - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - diskEncryptionSetResourceId: nestedDependencies.outputs.diskEncryptionSetResourceId - openServiceMeshEnabled: true - enableStorageProfileBlobCSIDriver: true - enableStorageProfileDiskCSIDriver: true - enableStorageProfileFileCSIDriver: true - enableStorageProfileSnapshotController: true - managedIdentities: { - userAssignedResourcesIds: [ - nestedDependencies.outputs.managedIdentityResourceId +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + primaryAgentPoolProfile: [ + { + availabilityZones: [ + '3' + ] + count: 1 + enableAutoScaling: true + maxCount: 3 + maxPods: 30 + minCount: 1 + mode: 'System' + name: 'systempool' + osDiskSizeGB: 0 + osType: 'Linux' + serviceCidr: '' + type: 'VirtualMachineScaleSets' + vmSize: 'Standard_DS2_v2' + vnetSubnetID: nestedDependencies.outputs.subnetResourceIds[0] + } ] - } - identityProfile: { - kubeletidentity: { - resourceId: nestedDependencies.outputs.managedIdentityKubeletIdentityResourceId - } - } - omsAgentEnabled: true - monitoringWorkspaceId: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId - enableAzureDefender: true - enableKeyvaultSecretsProvider: true - enablePodSecurityPolicy: false - enableAzureMonitorProfileMetrics: true - customerManagedKey: { - keyName: nestedDependencies.outputs.keyVaultEncryptionKeyName - keyVaultNetworkAccess: 'Public' - keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - } - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + agentPools: [ + { + availabilityZones: [ + '3' + ] + count: 2 + enableAutoScaling: true + maxCount: 3 + maxPods: 30 + minCount: 1 + minPods: 2 + mode: 'User' + name: 'userpool1' + nodeLabels: {} + nodeTaints: [ + 'CriticalAddonsOnly=true:NoSchedule' + ] + osDiskSizeGB: 128 + osType: 'Linux' + scaleSetEvictionPolicy: 'Delete' + scaleSetPriority: 'Regular' + type: 'VirtualMachineScaleSets' + vmSize: 'Standard_DS2_v2' + vnetSubnetID: nestedDependencies.outputs.subnetResourceIds[1] + proximityPlacementGroupResourceId: nestedDependencies.outputs.proximityPlacementGroupResourceId + } + { + availabilityZones: [ + '3' + ] + count: 2 + enableAutoScaling: true + maxCount: 3 + maxPods: 30 + minCount: 1 + minPods: 2 + mode: 'User' + name: 'userpool2' + nodeLabels: {} + nodeTaints: [ + 'CriticalAddonsOnly=true:NoSchedule' + ] + osDiskSizeGB: 128 + osType: 'Linux' + scaleSetEvictionPolicy: 'Delete' + scaleSetPriority: 'Regular' + type: 'VirtualMachineScaleSets' + vmSize: 'Standard_DS2_v2' + vnetSubnetID: nestedDependencies.outputs.subnetResourceIds[2] + } + ] + autoUpgradeProfileUpgradeChannel: 'stable' + enableWorkloadIdentity: true + enableOidcIssuerProfile: true + networkPlugin: 'azure' + networkDataplane: 'azure' + networkPluginMode: 'overlay' + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + diskEncryptionSetResourceId: nestedDependencies.outputs.diskEncryptionSetResourceId + openServiceMeshEnabled: true + enableStorageProfileBlobCSIDriver: true + enableStorageProfileDiskCSIDriver: true + enableStorageProfileFileCSIDriver: true + enableStorageProfileSnapshotController: true + managedIdentities: { + userAssignedResourcesIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + identityProfile: { + kubeletidentity: { + resourceId: nestedDependencies.outputs.managedIdentityKubeletIdentityResourceId + } } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + omsAgentEnabled: true + monitoringWorkspaceId: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId + enableAzureDefender: true + enableKeyvaultSecretsProvider: true + enablePodSecurityPolicy: false + enableAzureMonitorProfileMetrics: true + customerManagedKey: { + keyName: nestedDependencies.outputs.keyVaultEncryptionKeyName + keyVaultNetworkAccess: 'Public' + keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - fluxExtension: { - configurationSettings: { - 'helm-controller.enabled': 'true' - 'source-controller.enabled': 'true' - 'kustomize-controller.enabled': 'true' - 'notification-controller.enabled': 'true' - 'image-automation-controller.enabled': 'false' - 'image-reflector-controller.enabled': 'false' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - configurations: [ + roleAssignments: [ { - namespace: 'flux-system' - scope: 'cluster' - gitRepository: { - repositoryRef: { - branch: 'main' - } - sshKnownHosts: '' - syncIntervalInSeconds: 300 - timeoutInSeconds: 180 - url: 'https://github.com/mspnp/aks-baseline' - } + roleDefinitionIdOrName: 'Owner' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' } { - namespace: 'flux-system-helm' - scope: 'cluster' - gitRepository: { - repositoryRef: { - branch: 'main' + 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' + Role: 'DeploymentValidation' + } + fluxExtension: { + configurationSettings: { + 'helm-controller.enabled': 'true' + 'source-controller.enabled': 'true' + 'kustomize-controller.enabled': 'true' + 'notification-controller.enabled': 'true' + 'image-automation-controller.enabled': 'false' + 'image-reflector-controller.enabled': 'false' + } + configurations: [ + { + namespace: 'flux-system' + scope: 'cluster' + gitRepository: { + repositoryRef: { + branch: 'main' + } + sshKnownHosts: '' + syncIntervalInSeconds: 300 + timeoutInSeconds: 180 + url: 'https://github.com/mspnp/aks-baseline' } - sshKnownHosts: '' - syncIntervalInSeconds: 300 - timeoutInSeconds: 180 - url: 'https://github.com/Azure/gitops-flux2-kustomize-helm-mt' } - kustomizations: { - infra: { - path: './infrastructure' - dependsOn: [] - timeoutInSeconds: 600 - syncIntervalInSeconds: 600 - validation: 'none' - prune: true + { + namespace: 'flux-system-helm' + scope: 'cluster' + gitRepository: { + repositoryRef: { + branch: 'main' + } + sshKnownHosts: '' + syncIntervalInSeconds: 300 + timeoutInSeconds: 180 + url: 'https://github.com/Azure/gitops-flux2-kustomize-helm-mt' } - apps: { - path: './apps/staging' - dependsOn: [ - 'infra' - ] - timeoutInSeconds: 600 - syncIntervalInSeconds: 600 - retryIntervalInSeconds: 120 - prune: true + kustomizations: { + infra: { + path: './infrastructure' + dependsOn: [] + timeoutInSeconds: 600 + syncIntervalInSeconds: 600 + validation: 'none' + prune: true + } + apps: { + path: './apps/staging' + dependsOn: [ + 'infra' + ] + timeoutInSeconds: 600 + syncIntervalInSeconds: 600 + retryIntervalInSeconds: 120 + prune: true + } } } - } - ] + ] + } } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/container-service/managed-cluster/tests/e2e/defaults/main.test.bicep b/avm/res/container-service/managed-cluster/tests/e2e/defaults/main.test.bicep index b212dcf8f8..fbeddb2b7e 100644 --- a/avm/res/container-service/managed-cluster/tests/e2e/defaults/main.test.bicep +++ b/avm/res/container-service/managed-cluster/tests/e2e/defaults/main.test.bicep @@ -32,22 +32,24 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { } @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 - } - primaryAgentPoolProfile: [ - { - name: 'systempool' - count: 1 - vmSize: 'Standard_DS2_v2' - mode: 'System' +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 } - ] + primaryAgentPoolProfile: [ + { + name: 'systempool' + count: 1 + vmSize: 'Standard_DS2_v2' + mode: 'System' + } + ] + } } -}] +] diff --git a/avm/res/container-service/managed-cluster/tests/e2e/kubenet/dependencies.bicep b/avm/res/container-service/managed-cluster/tests/e2e/kubenet/dependencies.bicep index bcd58414ee..e564f5c4b6 100644 --- a/avm/res/container-service/managed-cluster/tests/e2e/kubenet/dependencies.bicep +++ b/avm/res/container-service/managed-cluster/tests/e2e/kubenet/dependencies.bicep @@ -8,13 +8,13 @@ param managedIdentityName string param dnsZoneName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } resource dnsZone 'Microsoft.Network/dnsZones@2018-05-01' = { - name: dnsZoneName - location: 'global' + name: dnsZoneName + location: 'global' } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/container-service/managed-cluster/tests/e2e/kubenet/main.test.bicep b/avm/res/container-service/managed-cluster/tests/e2e/kubenet/main.test.bicep index ce9e1930c8..5b2adb181b 100644 --- a/avm/res/container-service/managed-cluster/tests/e2e/kubenet/main.test.bicep +++ b/avm/res/container-service/managed-cluster/tests/e2e/kubenet/main.test.bicep @@ -60,124 +60,129 @@ 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 - primaryAgentPoolProfile: [ - { - availabilityZones: [ - '3' - ] - count: 1 - enableAutoScaling: true - maxCount: 3 - maxPods: 30 - minCount: 1 - mode: 'System' - name: 'systempool' - osDiskSizeGB: 0 - osType: 'Linux' - serviceCidr: '' - type: 'VirtualMachineScaleSets' - vmSize: 'Standard_DS2_v2' - } - ] - agentPools: [ - { - availabilityZones: [ - '3' - ] - count: 2 - enableAutoScaling: true - maxCount: 3 - maxPods: 30 - minCount: 1 - minPods: 2 - mode: 'User' - name: 'userpool1' - nodeLabels: {} - nodeTaints: [ - 'CriticalAddonsOnly=true:NoSchedule' - ] - osDiskSizeGB: 128 - osType: 'Linux' - scaleSetEvictionPolicy: 'Delete' - scaleSetPriority: 'Regular' - type: 'VirtualMachineScaleSets' - vmSize: 'Standard_DS2_v2' - } - { - availabilityZones: [ - '3' - ] - count: 2 - enableAutoScaling: true - maxCount: 3 - maxPods: 30 - minCount: 1 - minPods: 2 - mode: 'User' - name: 'userpool2' - nodeLabels: {} - nodeTaints: [ - 'CriticalAddonsOnly=true:NoSchedule' - ] - osDiskSizeGB: 128 - osType: 'Linux' - scaleSetEvictionPolicy: 'Delete' - scaleSetPriority: 'Regular' - type: 'VirtualMachineScaleSets' - vmSize: 'Standard_DS2_v2' - } - ] - networkPlugin: 'kubenet' - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } +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 + primaryAgentPoolProfile: [ + { + availabilityZones: [ + '3' + ] + count: 1 + enableAutoScaling: true + maxCount: 3 + maxPods: 30 + minCount: 1 + mode: 'System' + name: 'systempool' + osDiskSizeGB: 0 + osType: 'Linux' + serviceCidr: '' + type: 'VirtualMachineScaleSets' + vmSize: 'Standard_DS2_v2' + } + ] + agentPools: [ + { + availabilityZones: [ + '3' + ] + count: 2 + enableAutoScaling: true + maxCount: 3 + maxPods: 30 + minCount: 1 + minPods: 2 + mode: 'User' + name: 'userpool1' + nodeLabels: {} + nodeTaints: [ + 'CriticalAddonsOnly=true:NoSchedule' + ] + osDiskSizeGB: 128 + osType: 'Linux' + scaleSetEvictionPolicy: 'Delete' + scaleSetPriority: 'Regular' + type: 'VirtualMachineScaleSets' + vmSize: 'Standard_DS2_v2' + } + { + availabilityZones: [ + '3' + ] + count: 2 + enableAutoScaling: true + maxCount: 3 + maxPods: 30 + minCount: 1 + minPods: 2 + mode: 'User' + name: 'userpool2' + nodeLabels: {} + nodeTaints: [ + 'CriticalAddonsOnly=true:NoSchedule' + ] + osDiskSizeGB: 128 + osType: 'Linux' + scaleSetEvictionPolicy: 'Delete' + scaleSetPriority: 'Regular' + type: 'VirtualMachineScaleSets' + vmSize: 'Standard_DS2_v2' + } + ] + networkPlugin: 'kubenet' + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + 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' + } + ] + managedIdentities: { + userAssignedResourcesIds: [ + nestedDependencies.outputs.managedIdentityResourceId ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - 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' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - managedIdentities: { - userAssignedResourcesIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/container-service/managed-cluster/tests/e2e/priv/dependencies.bicep b/avm/res/container-service/managed-cluster/tests/e2e/priv/dependencies.bicep index b74bb113ac..eab20c41e4 100644 --- a/avm/res/container-service/managed-cluster/tests/e2e/priv/dependencies.bicep +++ b/avm/res/container-service/managed-cluster/tests/e2e/priv/dependencies.bicep @@ -59,7 +59,10 @@ resource msiVnetRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04- scope: virtualNetwork properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') // Network Contributor + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '4d97b98b-1d4f-4787-a291-c67834d212e7' + ) // Network Contributor principalType: 'ServicePrincipal' } } @@ -69,7 +72,10 @@ resource msiPrivDnsZoneRoleAssignment 'Microsoft.Authorization/roleAssignments@2 scope: privateDnsZone properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f') // Private DNS Zone Contributor + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b12aa53e-6015-4669-85d0-8515ebb3ae7f' + ) // Private DNS Zone Contributor principalType: 'ServicePrincipal' } } diff --git a/avm/res/container-service/managed-cluster/tests/e2e/priv/main.test.bicep b/avm/res/container-service/managed-cluster/tests/e2e/priv/main.test.bicep index 57372d1425..4c6b264529 100644 --- a/avm/res/container-service/managed-cluster/tests/e2e/priv/main.test.bicep +++ b/avm/res/container-service/managed-cluster/tests/e2e/priv/main.test.bicep @@ -47,94 +47,96 @@ 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 - enablePrivateCluster: true - primaryAgentPoolProfile: [ - { - availabilityZones: [ - '3' - ] - count: 1 - enableAutoScaling: true - maxCount: 3 - maxPods: 30 - minCount: 1 - mode: 'System' - name: 'systempool' - osDiskSizeGB: 0 - osType: 'Linux' - serviceCidr: '' - type: 'VirtualMachineScaleSets' - vmSize: 'Standard_DS2_v2' - vnetSubnetID: '${nestedDependencies.outputs.vNetResourceId}/subnets/defaultSubnet' - } - ] - agentPools: [ - { - availabilityZones: [ - '3' - ] - count: 2 - enableAutoScaling: true - maxCount: 3 - maxPods: 30 - minCount: 1 - minPods: 2 - mode: 'User' - name: 'userpool1' - nodeLabels: {} - nodeTaints: [ - 'CriticalAddonsOnly=true:NoSchedule' - ] - osDiskSizeGB: 128 - osType: 'Linux' - scaleSetEvictionPolicy: 'Delete' - scaleSetPriority: 'Regular' - type: 'VirtualMachineScaleSets' - vmSize: 'Standard_DS2_v2' - vnetSubnetID: '${nestedDependencies.outputs.vNetResourceId}/subnets/defaultSubnet' - } - { - availabilityZones: [ - '3' - ] - count: 2 - enableAutoScaling: true - maxCount: 3 - maxPods: 30 - minCount: 1 - minPods: 2 - mode: 'User' - name: 'userpool2' - nodeLabels: {} - nodeTaints: [ - 'CriticalAddonsOnly=true:NoSchedule' +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 + enablePrivateCluster: true + primaryAgentPoolProfile: [ + { + availabilityZones: [ + '3' + ] + count: 1 + enableAutoScaling: true + maxCount: 3 + maxPods: 30 + minCount: 1 + mode: 'System' + name: 'systempool' + osDiskSizeGB: 0 + osType: 'Linux' + serviceCidr: '' + type: 'VirtualMachineScaleSets' + vmSize: 'Standard_DS2_v2' + vnetSubnetID: '${nestedDependencies.outputs.vNetResourceId}/subnets/defaultSubnet' + } + ] + agentPools: [ + { + availabilityZones: [ + '3' + ] + count: 2 + enableAutoScaling: true + maxCount: 3 + maxPods: 30 + minCount: 1 + minPods: 2 + mode: 'User' + name: 'userpool1' + nodeLabels: {} + nodeTaints: [ + 'CriticalAddonsOnly=true:NoSchedule' + ] + osDiskSizeGB: 128 + osType: 'Linux' + scaleSetEvictionPolicy: 'Delete' + scaleSetPriority: 'Regular' + type: 'VirtualMachineScaleSets' + vmSize: 'Standard_DS2_v2' + vnetSubnetID: '${nestedDependencies.outputs.vNetResourceId}/subnets/defaultSubnet' + } + { + availabilityZones: [ + '3' + ] + count: 2 + enableAutoScaling: true + maxCount: 3 + maxPods: 30 + minCount: 1 + minPods: 2 + mode: 'User' + name: 'userpool2' + nodeLabels: {} + nodeTaints: [ + 'CriticalAddonsOnly=true:NoSchedule' + ] + osDiskSizeGB: 128 + osType: 'Linux' + scaleSetEvictionPolicy: 'Delete' + scaleSetPriority: 'Regular' + type: 'VirtualMachineScaleSets' + vmSize: 'Standard_DS2_v2' + } + ] + networkPlugin: 'azure' + skuTier: 'Standard' + dnsServiceIP: '10.10.200.10' + serviceCidr: '10.10.200.0/24' + privateDNSZone: nestedDependencies.outputs.privateDnsZoneResourceId + managedIdentities: { + userAssignedResourcesIds: [ + nestedDependencies.outputs.managedIdentityResourceId ] - osDiskSizeGB: 128 - osType: 'Linux' - scaleSetEvictionPolicy: 'Delete' - scaleSetPriority: 'Regular' - type: 'VirtualMachineScaleSets' - vmSize: 'Standard_DS2_v2' } - ] - networkPlugin: 'azure' - skuTier: 'Standard' - dnsServiceIP: '10.10.200.10' - serviceCidr: '10.10.200.0/24' - privateDNSZone: nestedDependencies.outputs.privateDnsZoneResourceId - managedIdentities: { - userAssignedResourcesIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/container-service/managed-cluster/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/container-service/managed-cluster/tests/e2e/waf-aligned/dependencies.bicep index b74bb113ac..eab20c41e4 100644 --- a/avm/res/container-service/managed-cluster/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/container-service/managed-cluster/tests/e2e/waf-aligned/dependencies.bicep @@ -59,7 +59,10 @@ resource msiVnetRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04- scope: virtualNetwork properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') // Network Contributor + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '4d97b98b-1d4f-4787-a291-c67834d212e7' + ) // Network Contributor principalType: 'ServicePrincipal' } } @@ -69,7 +72,10 @@ resource msiPrivDnsZoneRoleAssignment 'Microsoft.Authorization/roleAssignments@2 scope: privateDnsZone properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f') // Private DNS Zone Contributor + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b12aa53e-6015-4669-85d0-8515ebb3ae7f' + ) // Private DNS Zone Contributor principalType: 'ServicePrincipal' } } diff --git a/avm/res/container-service/managed-cluster/tests/e2e/waf-aligned/main.test.bicep b/avm/res/container-service/managed-cluster/tests/e2e/waf-aligned/main.test.bicep index 98b0174d2d..0c67fcdcb0 100644 --- a/avm/res/container-service/managed-cluster/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/container-service/managed-cluster/tests/e2e/waf-aligned/main.test.bicep @@ -63,136 +63,138 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 - enablePrivateCluster: true - primaryAgentPoolProfile: [ - { - availabilityZones: [ - '3' - ] - count: 3 - enableAutoScaling: true - maxCount: 3 - maxPods: 50 - minCount: 1 - mode: 'System' - name: 'systempool' - osDiskSizeGB: 0 - osType: 'Linux' - serviceCidr: '' - type: 'VirtualMachineScaleSets' - vmSize: 'Standard_DS2_v2' - vnetSubnetID: '${nestedDependencies.outputs.vNetResourceId}/subnets/defaultSubnet' - } - ] - agentPools: [ - { - availabilityZones: [ - '3' - ] - count: 2 - enableAutoScaling: true - maxCount: 3 - maxPods: 50 - minCount: 1 - minPods: 2 - mode: 'User' - name: 'userpool1' - nodeLabels: {} - nodeTaints: [ - 'CriticalAddonsOnly=true:NoSchedule' - ] - osDiskType: 'Ephemeral' - osDiskSizeGB: 60 - osType: 'Linux' - scaleSetEvictionPolicy: 'Delete' - scaleSetPriority: 'Regular' - type: 'VirtualMachineScaleSets' - vmSize: 'Standard_DS2_v2' - vnetSubnetID: '${nestedDependencies.outputs.vNetResourceId}/subnets/defaultSubnet' - } - { - availabilityZones: [ - '3' - ] - count: 2 - enableAutoScaling: true - maxCount: 3 - maxPods: 50 - minCount: 1 - minPods: 2 - mode: 'User' - name: 'userpool2' - nodeLabels: {} - nodeTaints: [ - 'CriticalAddonsOnly=true:NoSchedule' +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 + enablePrivateCluster: true + primaryAgentPoolProfile: [ + { + availabilityZones: [ + '3' + ] + count: 3 + enableAutoScaling: true + maxCount: 3 + maxPods: 50 + minCount: 1 + mode: 'System' + name: 'systempool' + osDiskSizeGB: 0 + osType: 'Linux' + serviceCidr: '' + type: 'VirtualMachineScaleSets' + vmSize: 'Standard_DS2_v2' + vnetSubnetID: '${nestedDependencies.outputs.vNetResourceId}/subnets/defaultSubnet' + } + ] + agentPools: [ + { + availabilityZones: [ + '3' + ] + count: 2 + enableAutoScaling: true + maxCount: 3 + maxPods: 50 + minCount: 1 + minPods: 2 + mode: 'User' + name: 'userpool1' + nodeLabels: {} + nodeTaints: [ + 'CriticalAddonsOnly=true:NoSchedule' + ] + osDiskType: 'Ephemeral' + osDiskSizeGB: 60 + osType: 'Linux' + scaleSetEvictionPolicy: 'Delete' + scaleSetPriority: 'Regular' + type: 'VirtualMachineScaleSets' + vmSize: 'Standard_DS2_v2' + vnetSubnetID: '${nestedDependencies.outputs.vNetResourceId}/subnets/defaultSubnet' + } + { + availabilityZones: [ + '3' + ] + count: 2 + enableAutoScaling: true + maxCount: 3 + maxPods: 50 + minCount: 1 + minPods: 2 + mode: 'User' + name: 'userpool2' + nodeLabels: {} + nodeTaints: [ + 'CriticalAddonsOnly=true:NoSchedule' + ] + osDiskType: 'Ephemeral' + osDiskSizeGB: 60 + osType: 'Linux' + scaleSetEvictionPolicy: 'Delete' + scaleSetPriority: 'Regular' + type: 'VirtualMachineScaleSets' + vmSize: 'Standard_DS2_v2' + } + ] + autoUpgradeProfileUpgradeChannel: 'stable' + networkPlugin: 'azure' + networkPolicy: 'azure' + skuTier: 'Standard' + dnsServiceIP: '10.10.200.10' + serviceCidr: '10.10.200.0/24' + omsAgentEnabled: true + monitoringWorkspaceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + disableLocalAccounts: true + enableAzureDefender: true + diagnosticSettings: [ + { + name: 'customSetting' + logCategoriesAndGroups: [ + { + category: 'kube-apiserver' + } + { + category: 'kube-controller-manager' + } + { + category: 'kube-scheduler' + } + { + category: 'cluster-autoscaler' + } + ] + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + privateDNSZone: nestedDependencies.outputs.privateDnsZoneResourceId + managedIdentities: { + userAssignedResourcesIds: [ + nestedDependencies.outputs.managedIdentityResourceId ] - osDiskType: 'Ephemeral' - osDiskSizeGB: 60 - osType: 'Linux' - scaleSetEvictionPolicy: 'Delete' - scaleSetPriority: 'Regular' - type: 'VirtualMachineScaleSets' - vmSize: 'Standard_DS2_v2' } - ] - autoUpgradeProfileUpgradeChannel: 'stable' - networkPlugin: 'azure' - networkPolicy: 'azure' - skuTier: 'Standard' - dnsServiceIP: '10.10.200.10' - serviceCidr: '10.10.200.0/24' - omsAgentEnabled: true - monitoringWorkspaceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - disableLocalAccounts: true - enableAzureDefender: true - diagnosticSettings: [ - { - name: 'customSetting' - logCategoriesAndGroups: [ - { - category: 'kube-apiserver' - } - { - category: 'kube-controller-manager' - } - { - category: 'kube-scheduler' - } - { - category: 'cluster-autoscaler' - } - ] - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - privateDNSZone: nestedDependencies.outputs.privateDnsZoneResourceId - managedIdentities: { - userAssignedResourcesIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/data-protection/backup-vault/backup-policy/main.json b/avm/res/data-protection/backup-vault/backup-policy/main.json index 052a79bdb4..4590e10872 100644 --- a/avm/res/data-protection/backup-vault/backup-policy/main.json +++ b/avm/res/data-protection/backup-vault/backup-policy/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3601741933922377880" + "version": "0.26.54.24096", + "templateHash": "11424915933898928003" }, "name": "Data Protection Backup Vault Backup Policies", "description": "This module deploys a Data Protection Backup Vault Backup Policy.", diff --git a/avm/res/data-protection/backup-vault/main.bicep b/avm/res/data-protection/backup-vault/main.bicep index 48648bcf2b..3c8a00201d 100644 --- a/avm/res/data-protection/backup-vault/main.bicep +++ b/avm/res/data-protection/backup-vault/main.bicep @@ -55,38 +55,56 @@ param securitySettings object = {} @description('Optional. Feature settings for the backup vault.') param featureSettings object = {} -var identity = !empty(managedIdentities) ? { - type: (managedIdentities.?systemAssigned ?? false) ? 'SystemAssigned' : null -} : null +var identity = !empty(managedIdentities) + ? { + type: (managedIdentities.?systemAssigned ?? false) ? 'SystemAssigned' : null + } + : null var builtInRoleNames = { - 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') - 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') - 'Backup Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a795c7a0-d4a2-40c1-ae25-d81f01202912') + 'Backup Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '5e467623-bb1f-42f4-a55d-6e525e11384b' + ) + 'Backup Operator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '00c29273-979b-4161-815c-10b084fb9324' + ) + 'Backup Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'a795c7a0-d4a2-40c1-ae25-d81f01202912' + ) 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.dataprotection-backupvault.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.dataprotection-backupvault.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource backupVault 'Microsoft.DataProtection/backupVaults@2023-05-01' = { name: name @@ -110,37 +128,48 @@ resource backupVault 'Microsoft.DataProtection/backupVaults@2023-05-01' = { } } -module backupVault_backupPolicies 'backup-policy/main.bicep' = [for (backupPolicy, index) in backupPolicies: { - name: '${uniqueString(deployment().name, location)}-BV-BackupPolicy-${index}' - params: { - backupVaultName: backupVault.name - name: backupPolicy.name - properties: backupPolicy.properties +module backupVault_backupPolicies 'backup-policy/main.bicep' = [ + for (backupPolicy, index) in backupPolicies: { + name: '${uniqueString(deployment().name, location)}-BV-BackupPolicy-${index}' + params: { + backupVaultName: backupVault.name + name: backupPolicy.name + properties: backupPolicy.properties + } } -}] - -resource backupVault_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.' +] + +resource backupVault_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: backupVault } - scope: backupVault -} -resource backupVault_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(backupVault.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource backupVault_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(backupVault.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: backupVault } - scope: backupVault -}] +] @description('The resource ID of the backup vault.') output resourceId string = backupVault.id diff --git a/avm/res/data-protection/backup-vault/main.json b/avm/res/data-protection/backup-vault/main.json index c43d9cb3c2..47ec72bf63 100644 --- a/avm/res/data-protection/backup-vault/main.json +++ b/avm/res/data-protection/backup-vault/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11297894401927654762" + "version": "0.26.54.24096", + "templateHash": "17999944940585257784" }, "name": "Data Protection Backup Vaults", "description": "This module deploys a Data Protection Backup Vault.", @@ -344,8 +344,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3601741933922377880" + "version": "0.26.54.24096", + "templateHash": "11424915933898928003" }, "name": "Data Protection Backup Vault Backup Policies", "description": "This module deploys a Data Protection Backup Vault Backup Policy.", diff --git a/avm/res/data-protection/backup-vault/tests/e2e/defaults/main.test.bicep b/avm/res/data-protection/backup-vault/tests/e2e/defaults/main.test.bicep index c908151dba..9021d7db82 100644 --- a/avm/res/data-protection/backup-vault/tests/e2e/defaults/main.test.bicep +++ b/avm/res/data-protection/backup-vault/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 +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 + } } -}] +] diff --git a/avm/res/data-protection/backup-vault/tests/e2e/max/dependencies.bicep b/avm/res/data-protection/backup-vault/tests/e2e/max/dependencies.bicep index 0f0755a6f4..0b7f226c1a 100644 --- a/avm/res/data-protection/backup-vault/tests/e2e/max/dependencies.bicep +++ b/avm/res/data-protection/backup-vault/tests/e2e/max/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/data-protection/backup-vault/tests/e2e/max/main.test.bicep b/avm/res/data-protection/backup-vault/tests/e2e/max/main.test.bicep index fb264e4ff2..dea4591b1c 100644 --- a/avm/res/data-protection/backup-vault/tests/e2e/max/main.test.bicep +++ b/avm/res/data-protection/backup-vault/tests/e2e/max/main.test.bicep @@ -45,106 +45,111 @@ 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 - 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' +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 + 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' + } + ] + azureMonitorAlertSettingsAlertsForAllJobFailures: 'Disabled' + managedIdentities: { + systemAssigned: true } - ] - azureMonitorAlertSettingsAlertsForAllJobFailures: 'Disabled' - managedIdentities: { - systemAssigned: true - } - backupPolicies: [ - { - name: 'DefaultPolicy' - properties: { - datasourceTypes: [ - 'Microsoft.Compute/disks' - ] - objectType: 'BackupPolicy' - policyRules: [ - { - backupParameters: { - backupType: 'Incremental' - objectType: 'AzureBackupParams' - } - dataStore: { - dataStoreType: 'OperationalStore' - objectType: 'DataStoreInfoBase' - } - name: 'BackupDaily' - objectType: 'AzureBackupRule' - trigger: { - objectType: 'ScheduleBasedTriggerContext' - schedule: { - repeatingTimeIntervals: [ - 'R/2022-05-31T23:30:00+01:00/P1D' + backupPolicies: [ + { + name: 'DefaultPolicy' + properties: { + datasourceTypes: [ + 'Microsoft.Compute/disks' + ] + objectType: 'BackupPolicy' + policyRules: [ + { + backupParameters: { + backupType: 'Incremental' + objectType: 'AzureBackupParams' + } + dataStore: { + dataStoreType: 'OperationalStore' + objectType: 'DataStoreInfoBase' + } + name: 'BackupDaily' + objectType: 'AzureBackupRule' + trigger: { + objectType: 'ScheduleBasedTriggerContext' + schedule: { + repeatingTimeIntervals: [ + 'R/2022-05-31T23:30:00+01:00/P1D' + ] + timeZone: 'W. Europe Standard Time' + } + taggingCriteria: [ + { + isDefault: true + taggingPriority: 99 + tagInfo: { + id: 'Default_' + tagName: 'Default' + } + } ] - timeZone: 'W. Europe Standard Time' } - taggingCriteria: [ + } + { + isDefault: true + lifecycles: [ { - isDefault: true - taggingPriority: 99 - tagInfo: { - id: 'Default_' - tagName: 'Default' + deleteAfter: { + duration: 'P7D' + objectType: 'AbsoluteDeleteOption' + } + sourceDataStore: { + dataStoreType: 'OperationalStore' + objectType: 'DataStoreInfoBase' } + targetDataStoreCopySettings: [] } ] + name: 'Default' + objectType: 'AzureRetentionRule' } - } - { - isDefault: true - lifecycles: [ - { - deleteAfter: { - duration: 'P7D' - objectType: 'AbsoluteDeleteOption' - } - sourceDataStore: { - dataStoreType: 'OperationalStore' - objectType: 'DataStoreInfoBase' - } - targetDataStoreCopySettings: [] - } - ] - name: 'Default' - objectType: 'AzureRetentionRule' - } - ] + ] + } } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/data-protection/backup-vault/tests/e2e/waf-aligned/main.test.bicep b/avm/res/data-protection/backup-vault/tests/e2e/waf-aligned/main.test.bicep index 1bc01850e2..fd6fdf9a58 100644 --- a/avm/res/data-protection/backup-vault/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/data-protection/backup-vault/tests/e2e/waf-aligned/main.test.bicep @@ -36,86 +36,88 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 - azureMonitorAlertSettingsAlertsForAllJobFailures: 'Disabled' - managedIdentities: { - systemAssigned: true - } - backupPolicies: [ - { - name: 'DefaultPolicy' - properties: { - datasourceTypes: [ - 'Microsoft.Compute/disks' - ] - objectType: 'BackupPolicy' - policyRules: [ - { - backupParameters: { - backupType: 'Incremental' - objectType: 'AzureBackupParams' - } - dataStore: { - dataStoreType: 'OperationalStore' - objectType: 'DataStoreInfoBase' - } - name: 'BackupDaily' - objectType: 'AzureBackupRule' - trigger: { - objectType: 'ScheduleBasedTriggerContext' - schedule: { - repeatingTimeIntervals: [ - 'R/2022-05-31T23:30:00+01:00/P1D' +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 + azureMonitorAlertSettingsAlertsForAllJobFailures: 'Disabled' + managedIdentities: { + systemAssigned: true + } + backupPolicies: [ + { + name: 'DefaultPolicy' + properties: { + datasourceTypes: [ + 'Microsoft.Compute/disks' + ] + objectType: 'BackupPolicy' + policyRules: [ + { + backupParameters: { + backupType: 'Incremental' + objectType: 'AzureBackupParams' + } + dataStore: { + dataStoreType: 'OperationalStore' + objectType: 'DataStoreInfoBase' + } + name: 'BackupDaily' + objectType: 'AzureBackupRule' + trigger: { + objectType: 'ScheduleBasedTriggerContext' + schedule: { + repeatingTimeIntervals: [ + 'R/2022-05-31T23:30:00+01:00/P1D' + ] + timeZone: 'W. Europe Standard Time' + } + taggingCriteria: [ + { + isDefault: true + taggingPriority: 99 + tagInfo: { + id: 'Default_' + tagName: 'Default' + } + } ] - timeZone: 'W. Europe Standard Time' } - taggingCriteria: [ + } + { + isDefault: true + lifecycles: [ { - isDefault: true - taggingPriority: 99 - tagInfo: { - id: 'Default_' - tagName: 'Default' + deleteAfter: { + duration: 'P7D' + objectType: 'AbsoluteDeleteOption' + } + sourceDataStore: { + dataStoreType: 'OperationalStore' + objectType: 'DataStoreInfoBase' } + targetDataStoreCopySettings: [] } ] + name: 'Default' + objectType: 'AzureRetentionRule' } - } - { - isDefault: true - lifecycles: [ - { - deleteAfter: { - duration: 'P7D' - objectType: 'AbsoluteDeleteOption' - } - sourceDataStore: { - dataStoreType: 'OperationalStore' - objectType: 'DataStoreInfoBase' - } - targetDataStoreCopySettings: [] - } - ] - name: 'Default' - objectType: 'AzureRetentionRule' - } - ] + ] + } } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/db-for-my-sql/flexible-server/administrator/main.json b/avm/res/db-for-my-sql/flexible-server/administrator/main.json index 5480bf8dab..e4df947daa 100644 --- a/avm/res/db-for-my-sql/flexible-server/administrator/main.json +++ b/avm/res/db-for-my-sql/flexible-server/administrator/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "9797360516324373554" + "version": "0.26.54.24096", + "templateHash": "2817201491275445304" }, "name": "DBforMySQL Flexible Server Administrators", "description": "This module deploys a DBforMySQL Flexible Server Administrator.", diff --git a/avm/res/db-for-my-sql/flexible-server/database/main.json b/avm/res/db-for-my-sql/flexible-server/database/main.json index 96c3f0eeda..77895b3ecb 100644 --- a/avm/res/db-for-my-sql/flexible-server/database/main.json +++ b/avm/res/db-for-my-sql/flexible-server/database/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "1786501395002693358" + "version": "0.26.54.24096", + "templateHash": "9734848552595709363" }, "name": "DBforMySQL Flexible Server Databases", "description": "This module deploys a DBforMySQL Flexible Server Database.", diff --git a/avm/res/db-for-my-sql/flexible-server/firewall-rule/main.json b/avm/res/db-for-my-sql/flexible-server/firewall-rule/main.json index c4ec0e06bc..70bdf3643c 100644 --- a/avm/res/db-for-my-sql/flexible-server/firewall-rule/main.json +++ b/avm/res/db-for-my-sql/flexible-server/firewall-rule/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "1600222376229916804" + "version": "0.26.54.24096", + "templateHash": "2931317814738693960" }, "name": "DBforMySQL Flexible Server Firewall Rules", "description": "This module deploys a DBforMySQL Flexible Server Firewall Rule.", diff --git a/avm/res/db-for-my-sql/flexible-server/main.bicep b/avm/res/db-for-my-sql/flexible-server/main.bicep index 9d0bb2c610..a0e0389dd2 100644 --- a/avm/res/db-for-my-sql/flexible-server/main.bicep +++ b/avm/res/db-for-my-sql/flexible-server/main.bicep @@ -162,67 +162,101 @@ param diagnosticSettings diagnosticSettingType @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -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: !empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null - userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null -} : null +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: !empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null + } + : null var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'MySQL Backup And Export Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd18ad5f3-1baf-4119-b49b-d944edb1f9d0') + 'MySQL Backup And Export Operator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'd18ad5f3-1baf-4119-b49b-d944edb1f9d0' + ) 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') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.dbformysql-flexibleserver.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.dbformysql-flexibleserver.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} -resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId)) { - name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) - scope: resourceGroup(split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4]) - - resource cMKKey 'keys@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { - name: customerManagedKey.?keyName ?? 'dummyKey' +resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = + if (!empty(customerManagedKey.?keyVaultResourceId)) { + name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) + scope: resourceGroup( + split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], + split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4] + ) + + resource cMKKey 'keys@2023-02-01' existing = + if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { + name: customerManagedKey.?keyName ?? 'dummyKey' + } } -} -resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { - name: last(split(customerManagedKey.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) - scope: resourceGroup(split((customerManagedKey.?userAssignedIdentityResourceId ?? '//'), '/')[2], split((customerManagedKey.?userAssignedIdentityResourceId ?? '////'), '/')[4]) -} - -resource cMKGeoKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = if (!empty(customerManagedKeyGeo.?keyVaultResourceId)) { - name: last(split((customerManagedKeyGeo.?keyVaultResourceId ?? 'dummyVault'), '/')) - scope: resourceGroup(split((customerManagedKeyGeo.?keyVaultResourceId ?? '//'), '/')[2], split((customerManagedKeyGeo.?keyVaultResourceId ?? '////'), '/')[4]) +resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = + if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { + name: last(split(customerManagedKey.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) + scope: resourceGroup( + split((customerManagedKey.?userAssignedIdentityResourceId ?? '//'), '/')[2], + split((customerManagedKey.?userAssignedIdentityResourceId ?? '////'), '/')[4] + ) + } - resource cMKKey 'keys@2023-02-01' existing = if (!empty(customerManagedKeyGeo.?keyVaultResourceId) && !empty(customerManagedKeyGeo.?keyName)) { - name: customerManagedKeyGeo.?keyName ?? 'dummyKey' +resource cMKGeoKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = + if (!empty(customerManagedKeyGeo.?keyVaultResourceId)) { + name: last(split((customerManagedKeyGeo.?keyVaultResourceId ?? 'dummyVault'), '/')) + scope: resourceGroup( + split((customerManagedKeyGeo.?keyVaultResourceId ?? '//'), '/')[2], + split((customerManagedKeyGeo.?keyVaultResourceId ?? '////'), '/')[4] + ) + + resource cMKKey 'keys@2023-02-01' existing = + if (!empty(customerManagedKeyGeo.?keyVaultResourceId) && !empty(customerManagedKeyGeo.?keyName)) { + name: customerManagedKeyGeo.?keyName ?? 'dummyKey' + } } -} -resource cMKGeoUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = if (!empty(customerManagedKeyGeo.?userAssignedIdentityResourceId)) { - name: last(split(customerManagedKeyGeo.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) - scope: resourceGroup(split((customerManagedKeyGeo.?userAssignedIdentityResourceId ?? '//'), '/')[2], split((customerManagedKeyGeo.?userAssignedIdentityResourceId ?? '////'), '/')[4]) -} +resource cMKGeoUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = + if (!empty(customerManagedKeyGeo.?userAssignedIdentityResourceId)) { + name: last(split(customerManagedKeyGeo.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) + scope: resourceGroup( + split((customerManagedKeyGeo.?userAssignedIdentityResourceId ?? '//'), '/')[2], + split((customerManagedKeyGeo.?userAssignedIdentityResourceId ?? '////'), '/')[4] + ) + } resource flexibleServer 'Microsoft.DBforMySQL/flexibleServers@2022-09-30-preview' = { name: name @@ -242,27 +276,39 @@ resource flexibleServer 'Microsoft.DBforMySQL/flexibleServers@2022-09-30-preview geoRedundantBackup: geoRedundantBackup } createMode: createMode - dataEncryption: !empty(customerManagedKey) ? { - type: 'AzureKeyVault' - geoBackupKeyURI: geoRedundantBackup == 'Enabled' ? (!empty(customerManagedKeyGeo.?keyVersion ?? '') ? '${cMKGeoKeyVault::cMKKey.properties.keyUri}/${customerManagedKeyGeo!.keyVersion}' : cMKGeoKeyVault::cMKKey.properties.keyUriWithVersion) : null - geoBackupUserAssignedIdentityId: geoRedundantBackup == 'Enabled' ? cMKGeoUserAssignedIdentity.id : null - primaryKeyURI: !empty(customerManagedKey.?keyVersion ?? '') ? '${cMKKeyVault::cMKKey.properties.keyUri}/${customerManagedKey!.keyVersion}' : cMKKeyVault::cMKKey.properties.keyUriWithVersion - primaryUserAssignedIdentityId: cMKUserAssignedIdentity.id - } : null + dataEncryption: !empty(customerManagedKey) + ? { + type: 'AzureKeyVault' + geoBackupKeyURI: geoRedundantBackup == 'Enabled' + ? (!empty(customerManagedKeyGeo.?keyVersion ?? '') + ? '${cMKGeoKeyVault::cMKKey.properties.keyUri}/${customerManagedKeyGeo!.keyVersion}' + : cMKGeoKeyVault::cMKKey.properties.keyUriWithVersion) + : null + geoBackupUserAssignedIdentityId: geoRedundantBackup == 'Enabled' ? cMKGeoUserAssignedIdentity.id : null + primaryKeyURI: !empty(customerManagedKey.?keyVersion ?? '') + ? '${cMKKeyVault::cMKKey.properties.keyUri}/${customerManagedKey!.keyVersion}' + : cMKKeyVault::cMKKey.properties.keyUriWithVersion + primaryUserAssignedIdentityId: cMKUserAssignedIdentity.id + } + : null highAvailability: { mode: highAvailability standbyAvailabilityZone: highAvailability == 'SameZone' ? availabilityZone : null } - maintenanceWindow: !empty(maintenanceWindow) ? { - customWindow: maintenanceWindow.customWindow - dayOfWeek: maintenanceWindow.customWindow == 'Enabled' ? maintenanceWindow.dayOfWeek : 0 - startHour: maintenanceWindow.customWindow == 'Enabled' ? maintenanceWindow.startHour : 0 - startMinute: maintenanceWindow.customWindow == 'Enabled' ? maintenanceWindow.startMinute : 0 - } : null - network: !empty(delegatedSubnetResourceId) && empty(firewallRules) ? { - delegatedSubnetResourceId: delegatedSubnetResourceId - privateDnsZoneResourceId: privateDnsZoneResourceId - } : null + maintenanceWindow: !empty(maintenanceWindow) + ? { + customWindow: maintenanceWindow.customWindow + dayOfWeek: maintenanceWindow.customWindow == 'Enabled' ? maintenanceWindow.dayOfWeek : 0 + startHour: maintenanceWindow.customWindow == 'Enabled' ? maintenanceWindow.startHour : 0 + startMinute: maintenanceWindow.customWindow == 'Enabled' ? maintenanceWindow.startMinute : 0 + } + : null + network: !empty(delegatedSubnetResourceId) && empty(firewallRules) + ? { + delegatedSubnetResourceId: delegatedSubnetResourceId + privateDnsZoneResourceId: privateDnsZoneResourceId + } + : null replicationRole: replicationRole restorePointInTime: restorePointInTime sourceServerResourceId: !empty(sourceServerResourceId) ? sourceServerResourceId : null @@ -276,82 +322,103 @@ resource flexibleServer 'Microsoft.DBforMySQL/flexibleServers@2022-09-30-preview } } -resource flexibleServer_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.' +resource flexibleServer_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: flexibleServer } - scope: flexibleServer -} -resource flexibleServer_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(flexibleServer.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource flexibleServer_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(flexibleServer.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: flexibleServer } - scope: flexibleServer -}] - -module flexibleServer_databases 'database/main.bicep' = [for (database, index) in databases: { - name: '${uniqueString(deployment().name, location)}-MySQL-DB-${index}' - params: { - name: database.name - flexibleServerName: flexibleServer.name - collation: contains(database, 'collation') ? database.collation : '' - charset: contains(database, 'charset') ? database.charset : '' +] + +module flexibleServer_databases 'database/main.bicep' = [ + for (database, index) in databases: { + name: '${uniqueString(deployment().name, location)}-MySQL-DB-${index}' + params: { + name: database.name + flexibleServerName: flexibleServer.name + collation: contains(database, 'collation') ? database.collation : '' + charset: contains(database, 'charset') ? database.charset : '' + } } -}] - -module flexibleServer_firewallRules 'firewall-rule/main.bicep' = [for (firewallRule, index) in firewallRules: { - name: '${uniqueString(deployment().name, location)}-MySQL-FirewallRules-${index}' - params: { - name: firewallRule.name - flexibleServerName: flexibleServer.name - startIpAddress: firewallRule.startIpAddress - endIpAddress: firewallRule.endIpAddress +] + +module flexibleServer_firewallRules 'firewall-rule/main.bicep' = [ + for (firewallRule, index) in firewallRules: { + name: '${uniqueString(deployment().name, location)}-MySQL-FirewallRules-${index}' + params: { + name: firewallRule.name + flexibleServerName: flexibleServer.name + startIpAddress: firewallRule.startIpAddress + endIpAddress: firewallRule.endIpAddress + } } -}] - -module flexibleServer_administrators 'administrator/main.bicep' = [for (administrator, index) in administrators: { - name: '${uniqueString(deployment().name, location)}-MySQL-Administrators-${index}' - params: { - flexibleServerName: flexibleServer.name - login: administrator.login - sid: administrator.sid - identityResourceId: administrator.identityResourceId - tenantId: contains(administrator, 'tenantId') ? administrator.tenantId : tenant().tenantId +] + +module flexibleServer_administrators 'administrator/main.bicep' = [ + for (administrator, index) in administrators: { + name: '${uniqueString(deployment().name, location)}-MySQL-Administrators-${index}' + params: { + flexibleServerName: flexibleServer.name + login: administrator.login + sid: administrator.sid + identityResourceId: administrator.identityResourceId + tenantId: contains(administrator, 'tenantId') ? administrator.tenantId : tenant().tenantId + } } -}] - -resource flexibleServer_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +] + +resource flexibleServer_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: flexibleServer } - scope: flexibleServer -}] +] @description('The name of the deployed MySQL Flexible server.') output name string = flexibleServer.name diff --git a/avm/res/db-for-my-sql/flexible-server/tests/e2e/defaults/main.test.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/defaults/main.test.bicep index d13a62288a..8412371c66 100644 --- a/avm/res/db-for-my-sql/flexible-server/tests/e2e/defaults/main.test.bicep +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/defaults/main.test.bicep @@ -40,15 +40,17 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { // ============== // @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_B1ms' - tier: 'Burstable' +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_B1ms' + tier: 'Burstable' + } } -}] +] diff --git a/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/dependencies1.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/dependencies1.bicep index c1ed5dfa4c..4c1716bb23 100644 --- a/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/dependencies1.bicep +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/dependencies1.bicep @@ -8,38 +8,41 @@ param managedIdentityName string param pairedRegionScriptName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: managedIdentityName - location: location + 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' - } + 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') + name: pairedRegionScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} } - dependsOn: [ - roleAssignment - ] + } + 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.') diff --git a/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/dependencies2.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/dependencies2.bicep index 258d087ade..0077f627ce 100644 --- a/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/dependencies2.bicep +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/dependencies2.bicep @@ -17,85 +17,91 @@ param geoBackupManagedIdentityName string param geoBackupLocation string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } resource keyVault 'Microsoft.KeyVault/vaults@2023-02-01' = { - name: keyVaultName - location: location - properties: { - sku: { - family: 'A' - name: 'standard' - } - tenantId: tenant().tenantId - enablePurgeProtection: true - softDeleteRetentionInDays: 90 - enabledForTemplateDeployment: true - enabledForDiskEncryption: true - enabledForDeployment: true - enableRbacAuthorization: true - accessPolicies: [] + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' } - - resource key 'keys@2023-02-01' = { - name: 'keyEncryptionKey' - properties: { - kty: 'RSA' - } + tenantId: tenant().tenantId + enablePurgeProtection: true + softDeleteRetentionInDays: 90 + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } + + resource key 'keys@2023-02-01' = { + name: 'keyEncryptionKey' + properties: { + kty: 'RSA' } + } } resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid('msi-${keyVault::key.id}-${location}-${managedIdentity.id}-Key-Reader-RoleAssignment') - scope: keyVault::key - properties: { - principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User - principalType: 'ServicePrincipal' - } + name: guid('msi-${keyVault::key.id}-${location}-${managedIdentity.id}-Key-Reader-RoleAssignment') + scope: keyVault::key + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '12338af0-0e69-4776-bea7-57ae8d297424' + ) // Key Vault Crypto User + principalType: 'ServicePrincipal' + } } resource geoBackupManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: geoBackupManagedIdentityName - location: geoBackupLocation + name: geoBackupManagedIdentityName + location: geoBackupLocation } resource geoBackupKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' = { - name: geoBackupKeyVaultName - location: geoBackupLocation - properties: { - sku: { - family: 'A' - name: 'standard' - } - tenantId: tenant().tenantId - enablePurgeProtection: true - softDeleteRetentionInDays: 90 - enabledForTemplateDeployment: true - enabledForDiskEncryption: true - enabledForDeployment: true - enableRbacAuthorization: true - accessPolicies: [] + name: geoBackupKeyVaultName + location: geoBackupLocation + properties: { + sku: { + family: 'A' + name: 'standard' } - - resource key 'keys@2023-02-01' = { - name: 'keyEncryptionKey' - properties: { - kty: 'RSA' - } + tenantId: tenant().tenantId + enablePurgeProtection: true + softDeleteRetentionInDays: 90 + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } + + resource key 'keys@2023-02-01' = { + name: 'keyEncryptionKey' + properties: { + kty: 'RSA' } + } } resource geoBackupKeyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid('msi-${geoBackupKeyVault::key.id}-${geoBackupLocation}-${geoBackupManagedIdentity.id}-Key-Reader-RoleAssignment') - scope: geoBackupKeyVault::key - properties: { - principalId: geoBackupManagedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User - principalType: 'ServicePrincipal' - } + name: guid('msi-${geoBackupKeyVault::key.id}-${geoBackupLocation}-${geoBackupManagedIdentity.id}-Key-Reader-RoleAssignment') + scope: geoBackupKeyVault::key + properties: { + principalId: geoBackupManagedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '12338af0-0e69-4776-bea7-57ae8d297424' + ) // Key Vault Crypto User + principalType: 'ServicePrincipal' + } } @description('The resource ID of the created Managed Identity.') diff --git a/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep index 032e6b1e20..09db4d5368 100644 --- a/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep @@ -82,113 +82,117 @@ 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 - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies1.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies1.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies1.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - resourceType: 'MySQL Flexible Server' - serverName: '${namePrefix}${serviceShort}001' - } - administratorLogin: 'adminUserName' - administratorLoginPassword: password - skuName: 'Standard_D2ads_v5' - tier: 'GeneralPurpose' - storageAutoIoScaling: 'Enabled' - storageSizeGB: 64 - storageIOPS: 400 - backupRetentionDays: 20 - availabilityZone: '1' - databases: [ - { - - name: 'testdb1' +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 + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - name: 'testdb2' - charset: 'ascii' - collation: 'ascii_general_ci' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Owner' + principalId: nestedDependencies1.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + principalId: nestedDependencies1.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) + principalId: nestedDependencies1.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + resourceType: 'MySQL Flexible Server' + serverName: '${namePrefix}${serviceShort}001' } - ] - firewallRules: [ - { - endIpAddress: '0.0.0.0' - name: 'AllowAllWindowsAzureIps' - startIpAddress: '0.0.0.0' + administratorLogin: 'adminUserName' + administratorLoginPassword: password + skuName: 'Standard_D2ads_v5' + tier: 'GeneralPurpose' + storageAutoIoScaling: 'Enabled' + storageSizeGB: 64 + storageIOPS: 400 + backupRetentionDays: 20 + availabilityZone: '1' + databases: [ + { + name: 'testdb1' + } + { + name: 'testdb2' + charset: 'ascii' + collation: 'ascii_general_ci' + } + ] + firewallRules: [ + { + endIpAddress: '0.0.0.0' + name: 'AllowAllWindowsAzureIps' + startIpAddress: '0.0.0.0' + } + { + endIpAddress: '10.10.10.10' + name: 'test-rule1' + startIpAddress: '10.10.10.1' + } + { + endIpAddress: '100.100.100.10' + name: 'test-rule2' + startIpAddress: '100.100.100.1' + } + ] + highAvailability: 'SameZone' + storageAutoGrow: 'Enabled' + version: '8.0.21' + customerManagedKey: { + keyName: nestedDependencies2.outputs.keyName + keyVaultResourceId: nestedDependencies2.outputs.keyVaultResourceId + userAssignedIdentityResourceId: nestedDependencies2.outputs.managedIdentityResourceId } - { - endIpAddress: '10.10.10.10' - name: 'test-rule1' - startIpAddress: '10.10.10.1' + geoRedundantBackup: 'Enabled' + customerManagedKeyGeo: { + keyName: nestedDependencies2.outputs.geoBackupKeyName + keyVaultResourceId: nestedDependencies2.outputs.geoBackupKeyVaultResourceId + userAssignedIdentityResourceId: nestedDependencies2.outputs.geoBackupManagedIdentityResourceId } - { - endIpAddress: '100.100.100.10' - name: 'test-rule2' - startIpAddress: '100.100.100.1' + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies2.outputs.managedIdentityResourceId + nestedDependencies2.outputs.geoBackupManagedIdentityResourceId + ] } - ] - highAvailability: 'SameZone' - storageAutoGrow: 'Enabled' - version: '8.0.21' - customerManagedKey: { - keyName: nestedDependencies2.outputs.keyName - keyVaultResourceId: nestedDependencies2.outputs.keyVaultResourceId - userAssignedIdentityResourceId: nestedDependencies2.outputs.managedIdentityResourceId - } - geoRedundantBackup: 'Enabled' - customerManagedKeyGeo: { - keyName: nestedDependencies2.outputs.geoBackupKeyName - keyVaultResourceId: nestedDependencies2.outputs.geoBackupKeyVaultResourceId - userAssignedIdentityResourceId: nestedDependencies2.outputs.geoBackupManagedIdentityResourceId - } - managedIdentities: { - userAssignedResourceIds: [ - nestedDependencies2.outputs.managedIdentityResourceId - nestedDependencies2.outputs.geoBackupManagedIdentityResourceId + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } ] } - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } + dependsOn: [ + nestedDependencies1 + nestedDependencies2 + diagnosticDependencies ] } - dependsOn: [ - nestedDependencies1 - nestedDependencies2 - diagnosticDependencies - ] -}] +] diff --git a/avm/res/db-for-my-sql/flexible-server/tests/e2e/private/main.test.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/private/main.test.bicep index 9d8ab419ec..4966686565 100644 --- a/avm/res/db-for-my-sql/flexible-server/tests/e2e/private/main.test.bicep +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/private/main.test.bicep @@ -50,44 +50,45 @@ 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: resourceGroup.location - administratorLogin: 'adminUserName' - administratorLoginPassword: password - skuName: 'Standard_D2ds_v4' - tier: 'GeneralPurpose' - delegatedSubnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceId: nestedDependencies.outputs.privateDNSZoneResourceId - storageAutoIoScaling: 'Enabled' - storageSizeGB: 64 - storageIOPS: 400 - backupRetentionDays: 10 - databases: [ - { - - name: 'testdb1' +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: resourceGroup.location + administratorLogin: 'adminUserName' + administratorLoginPassword: password + skuName: 'Standard_D2ds_v4' + tier: 'GeneralPurpose' + delegatedSubnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceId: nestedDependencies.outputs.privateDNSZoneResourceId + storageAutoIoScaling: 'Enabled' + storageSizeGB: 64 + storageIOPS: 400 + backupRetentionDays: 10 + databases: [ + { + name: 'testdb1' + } + ] + highAvailability: 'SameZone' + storageAutoGrow: 'Enabled' + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] } - ] - highAvailability: 'SameZone' - storageAutoGrow: 'Enabled' - managedIdentities: { - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId + administrators: [ + { + identityResourceId: nestedDependencies.outputs.managedIdentityResourceId + login: nestedDependencies.outputs.managedIdentityName + sid: nestedDependencies.outputs.managedIdentityPrincipalId + } ] } - administrators: [ - { - identityResourceId: nestedDependencies.outputs.managedIdentityResourceId - login: nestedDependencies.outputs.managedIdentityName - sid: nestedDependencies.outputs.managedIdentityPrincipalId - } + dependsOn: [ + nestedDependencies ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/db-for-my-sql/flexible-server/tests/e2e/waf-aligned/main.test.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/waf-aligned/main.test.bicep index 0db1445062..9b2301311f 100644 --- a/avm/res/db-for-my-sql/flexible-server/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/waf-aligned/main.test.bicep @@ -42,24 +42,26 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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_B1ms' - tier: 'Burstable' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +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_B1ms' + tier: 'Burstable' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } } -}] +] 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 4c1e49e061..f4a72730ab 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.25.53.49325", - "templateHash": "14998758936357296642" + "version": "0.26.54.24096", + "templateHash": "4962117704341008645" }, "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/main.json b/avm/res/db-for-postgre-sql/flexible-server/configuration/main.json index c7a1671955..7bc951c35a 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 @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "13489282175455188314" + "version": "0.26.54.24096", + "templateHash": "15593908401685608166" }, "name": "DBforPostgreSQL Flexible Server Configurations", "description": "This module deploys a DBforPostgreSQL Flexible Server Configuration.", 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 d671937490..94e7c5dda2 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 @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "12415562574078248070" + "version": "0.26.54.24096", + "templateHash": "9123565269712158909" }, "name": "DBforPostgreSQL Flexible Server Databases", "description": "This module deploys a DBforPostgreSQL Flexible Server Database.", 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 d92c543ae2..a72ec6a432 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.25.53.49325", - "templateHash": "12878552829645985725" + "version": "0.26.54.24096", + "templateHash": "4295272529604037098" }, "name": "DBforPostgreSQL Flexible Server Firewall Rules", "description": "This module deploys a DBforPostgreSQL Flexible Server Firewall Rule.", diff --git a/avm/res/desktop-virtualization/application-group/application/main.json b/avm/res/desktop-virtualization/application-group/application/main.json index c5394ba356..c2a2d880fb 100644 --- a/avm/res/desktop-virtualization/application-group/application/main.json +++ b/avm/res/desktop-virtualization/application-group/application/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "1502648604355228279" + "version": "0.26.54.24096", + "templateHash": "11159515031632739969" }, "name": "Azure Virtual Desktop Application Group Application", "description": "This module deploys an Azure Virtual Desktop Application Group Application.", diff --git a/avm/res/desktop-virtualization/application-group/main.bicep b/avm/res/desktop-virtualization/application-group/main.bicep index 78c890153c..8ab27b64b1 100644 --- a/avm/res/desktop-virtualization/application-group/main.bicep +++ b/avm/res/desktop-virtualization/application-group/main.bicep @@ -68,23 +68,24 @@ var builtInRoleNames = { 'Managed Applications Reader': '/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44' } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.desktopvirtualization-appgroup.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.desktopvirtualization-appgroup.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource appGroup_hostpool 'Microsoft.DesktopVirtualization/hostPools@2022-09-09' existing = { name: hostpoolName @@ -102,62 +103,77 @@ resource appGroup 'Microsoft.DesktopVirtualization/applicationGroups@2023-09-05' } } -module appGroup_applications 'application/main.bicep' = [for (application, index) in applications: { - name: '${uniqueString(deployment().name, location)}-AppGroup-App-${index}' - params: { - name: application.name - applicationGroupName: appGroup.name - description: contains(application, 'description') ? application.description : '' - friendlyName: contains(application, 'friendlyName') ? application.friendlyName : appGroup.name - filePath: application.filePath - commandLineSetting: contains(application, 'commandLineSetting') ? application.commandLineSetting : 'DoNotAllow' - commandLineArguments: contains(application, 'commandLineArguments') ? application.commandLineArguments : '' - showInPortal: contains(application, 'showInPortal') ? application.showInPortal : false - iconPath: contains(application, 'iconPath') ? application.iconPath : application.filePath - iconIndex: contains(application, 'iconIndex') ? application.iconIndex : 0 +module appGroup_applications 'application/main.bicep' = [ + for (application, index) in applications: { + name: '${uniqueString(deployment().name, location)}-AppGroup-App-${index}' + params: { + name: application.name + applicationGroupName: appGroup.name + description: contains(application, 'description') ? application.description : '' + friendlyName: contains(application, 'friendlyName') ? application.friendlyName : appGroup.name + filePath: application.filePath + commandLineSetting: contains(application, 'commandLineSetting') ? application.commandLineSetting : 'DoNotAllow' + commandLineArguments: contains(application, 'commandLineArguments') ? application.commandLineArguments : '' + showInPortal: contains(application, 'showInPortal') ? application.showInPortal : false + iconPath: contains(application, 'iconPath') ? application.iconPath : application.filePath + iconIndex: contains(application, 'iconIndex') ? application.iconIndex : 0 + } } -}] - -resource appGroup_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.' +] + +resource appGroup_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: appGroup } - scope: appGroup -} -resource appGroup_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(appGroup.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - principalId: roleAssignment.principalId - description: roleAssignment.?description - principalType: roleAssignment.?principalType - condition: roleAssignment.?condition - conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null - delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId +resource appGroup_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(appGroup.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + principalId: roleAssignment.principalId + description: roleAssignment.?description + principalType: roleAssignment.?principalType + condition: roleAssignment.?condition + conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null + delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId + } + scope: appGroup } - scope: appGroup -}] - -resource appGroup_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +] + +resource appGroup_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: appGroup } - scope: appGroup -}] +] @sys.description('The resource ID of the scaling plan.') output resourceId string = appGroup.id diff --git a/avm/res/desktop-virtualization/application-group/main.json b/avm/res/desktop-virtualization/application-group/main.json index d2eeb102b7..53714466f4 100644 --- a/avm/res/desktop-virtualization/application-group/main.json +++ b/avm/res/desktop-virtualization/application-group/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16737123607848283739" + "version": "0.26.54.24096", + "templateHash": "11461831707158104939" }, "name": "Azure Virtual Desktop Application Group", "description": "This module deploys an Azure Virtual Desktop Application Group.", @@ -459,8 +459,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "1502648604355228279" + "version": "0.26.54.24096", + "templateHash": "11159515031632739969" }, "name": "Azure Virtual Desktop Application Group Application", "description": "This module deploys an Azure Virtual Desktop Application Group Application.", diff --git a/avm/res/desktop-virtualization/application-group/tests/e2e/defaults/main.test.bicep b/avm/res/desktop-virtualization/application-group/tests/e2e/defaults/main.test.bicep index 3f081725bf..bb93aa44a4 100644 --- a/avm/res/desktop-virtualization/application-group/tests/e2e/defaults/main.test.bicep +++ b/avm/res/desktop-virtualization/application-group/tests/e2e/defaults/main.test.bicep @@ -42,16 +42,18 @@ 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}002' - location: resourceLocation - applicationGroupType: 'Desktop' - hostpoolName: nestedDependencies.outputs.hostPoolName +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + location: resourceLocation + applicationGroupType: 'Desktop' + hostpoolName: nestedDependencies.outputs.hostPoolName + } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/desktop-virtualization/application-group/tests/e2e/max/main.test.bicep b/avm/res/desktop-virtualization/application-group/tests/e2e/max/main.test.bicep index 0b0141930b..6085203f7a 100644 --- a/avm/res/desktop-virtualization/application-group/tests/e2e/max/main.test.bicep +++ b/avm/res/desktop-virtualization/application-group/tests/e2e/max/main.test.bicep @@ -58,76 +58,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}002' - location: resourceLocation - applicationGroupType: 'RemoteApp' - applications: [ - { - commandLineArguments: '' - commandLineSetting: 'DoNotAllow' - description: 'Notepad by ARM template' - filePath: 'C:\\Windows\\System32\\notepad.exe' - friendlyName: 'Notepad' - iconIndex: 0 - iconPath: 'C:\\Windows\\System32\\notepad.exe' - name: 'notepad' - showInPortal: true +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + location: resourceLocation + applicationGroupType: 'RemoteApp' + applications: [ + { + commandLineArguments: '' + commandLineSetting: 'DoNotAllow' + description: 'Notepad by ARM template' + filePath: 'C:\\Windows\\System32\\notepad.exe' + friendlyName: 'Notepad' + iconIndex: 0 + iconPath: 'C:\\Windows\\System32\\notepad.exe' + name: 'notepad' + showInPortal: true + } + { + filePath: 'C:\\Program Files\\Windows NT\\Accessories\\wordpad.exe' + friendlyName: 'Wordpad' + name: 'wordpad' + } + ] + description: 'myDescription' + hostpoolName: nestedDependencies.outputs.hostPoolName + diagnosticSettings: [ + { + name: 'customSetting' + logCategoriesAndGroups: [ + { + categoryGroup: 'allLogs' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - filePath: 'C:\\Program Files\\Windows NT\\Accessories\\wordpad.exe' - friendlyName: 'Wordpad' - name: 'wordpad' - } - ] - description: 'myDescription' - hostpoolName: nestedDependencies.outputs.hostPoolName - diagnosticSettings: [ - { - name: 'customSetting' - logCategoriesAndGroups: [ - { - categoryGroup: 'allLogs' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' } - 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' - } + dependsOn: [ + nestedDependencies + diagnosticDependencies ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/desktop-virtualization/application-group/tests/e2e/waf-aligned/main.test.bicep b/avm/res/desktop-virtualization/application-group/tests/e2e/waf-aligned/main.test.bicep index c29e628c1d..17d4eb2d40 100644 --- a/avm/res/desktop-virtualization/application-group/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/desktop-virtualization/application-group/tests/e2e/waf-aligned/main.test.bicep @@ -57,29 +57,31 @@ 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}002' - location: resourceLocation - applicationGroupType: 'Desktop' - hostpoolName: nestedDependencies.outputs.hostPoolName - diagnosticSettings: [ - { - 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}002' + location: resourceLocation + applicationGroupType: 'Desktop' + hostpoolName: nestedDependencies.outputs.hostPoolName + diagnosticSettings: [ + { + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + tags: { + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/desktop-virtualization/host-pool/main.bicep b/avm/res/desktop-virtualization/host-pool/main.bicep index d173f8e6f0..4c2492ea35 100644 --- a/avm/res/desktop-virtualization/host-pool/main.bicep +++ b/avm/res/desktop-virtualization/host-pool/main.bicep @@ -147,23 +147,27 @@ var builtInRoleNames = { 'Managed Applications Reader': '/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44' } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: take('46d3xbcp.res.desktopvirtualization-hostpool.${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' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: take( + '46d3xbcp.res.desktopvirtualization-hostpool.${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' + } } } } } -} resource hostPool 'Microsoft.DesktopVirtualization/hostPools@2023-09-05' = { name: name @@ -196,88 +200,109 @@ resource hostPool 'Microsoft.DesktopVirtualization/hostPools@2023-09-05' = { } } -module hostPool_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-HostPool-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(hostPool.id, '/'))}-${privateEndpoint.?service ?? 'connection'}-${index}' - privateLinkServiceConnections: [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(hostPool.id, '/'))}-${privateEndpoint.?service ?? 'connection'}-${index}' - properties: { - privateLinkServiceId: hostPool.id - groupIds: [ - privateEndpoint.?service ?? 'connection' - ] +module hostPool_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-HostPool-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(hostPool.id, '/'))}-${privateEndpoint.?service ?? 'connection'}-${index}' + privateLinkServiceConnections: [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(hostPool.id, '/'))}-${privateEndpoint.?service ?? 'connection'}-${index}' + properties: { + privateLinkServiceId: hostPool.id + groupIds: [ + privateEndpoint.?service ?? 'connection' + ] + } } - } - ] - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(hostPool.id, '/'))}-${privateEndpoint.?service ?? 'connection'}-${index}' - properties: { - privateLinkServiceId: hostPool.id - groupIds: [ - privateEndpoint.?service ?? 'connection' + ] + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(hostPool.id, '/'))}-${privateEndpoint.?service ?? 'connection'}-${index}' + properties: { + privateLinkServiceId: hostPool.id + groupIds: [ + privateEndpoint.?service ?? 'connection' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] +] -resource hostPool_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.' +resource hostPool_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: hostPool } - scope: hostPool -} -resource hostPool_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(hostPool.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - principalId: roleAssignment.principalId - description: roleAssignment.?description - principalType: roleAssignment.?principalType - condition: roleAssignment.?condition - conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null - delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId +resource hostPool_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(hostPool.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + principalId: roleAssignment.principalId + description: roleAssignment.?description + principalType: roleAssignment.?principalType + condition: roleAssignment.?condition + conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null + delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId + } + scope: hostPool } - scope: hostPool -}] +] -resource hostPool_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource hostPool_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: hostPool } - scope: hostPool -}] +] @sys.description('The resource ID of the host pool.') output resourceId string = hostPool.id diff --git a/avm/res/desktop-virtualization/host-pool/main.json b/avm/res/desktop-virtualization/host-pool/main.json index 698856fcc8..61a90f36c2 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.25.53.49325", - "templateHash": "17476152824582806077" + "version": "0.26.54.24096", + "templateHash": "10100380447618545512" }, "name": "Azure Virtual Desktop Host Pool", "description": "This module deploys an Azure Virtual Desktop Host Pool", diff --git a/avm/res/desktop-virtualization/host-pool/tests/e2e/max/main.test.bicep b/avm/res/desktop-virtualization/host-pool/tests/e2e/max/main.test.bicep index bda485891a..ca82949ae4 100644 --- a/avm/res/desktop-virtualization/host-pool/tests/e2e/max/main.test.bicep +++ b/avm/res/desktop-virtualization/host-pool/tests/e2e/max/main.test.bicep @@ -133,7 +133,10 @@ module testDeployment '../../../main.bicep' = { principalType: 'ServicePrincipal' } { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) principalId: nestedDependencies.outputs.managedIdentityPrincipalId principalType: 'ServicePrincipal' } diff --git a/avm/res/desktop-virtualization/scaling-plan/main.bicep b/avm/res/desktop-virtualization/scaling-plan/main.bicep index 8f822e0e06..d16e592f20 100644 --- a/avm/res/desktop-virtualization/scaling-plan/main.bicep +++ b/avm/res/desktop-virtualization/scaling-plan/main.bicep @@ -66,23 +66,24 @@ var builtInRoleNames = { 'Desktop Virtualization Workspace Reader': '/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d' } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.desktopvirtualization-scalingplan.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.desktopvirtualization-scalingplan.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource scalingPlan 'Microsoft.DesktopVirtualization/scalingPlans@2022-09-09' = { name: name @@ -99,46 +100,59 @@ resource scalingPlan 'Microsoft.DesktopVirtualization/scalingPlans@2022-09-09' = } } -resource scalingPlan_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.' +resource scalingPlan_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: scalingPlan } - scope: scalingPlan -} -resource scalingPlan_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(scalingPlan.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource scalingPlan_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(scalingPlan.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: scalingPlan } - scope: scalingPlan -}] - -resource scalingPlan_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +] + +resource scalingPlan_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: scalingPlan } - scope: scalingPlan -}] +] @sys.description('The resource ID of the Scaling Plan.') output resourceId string = scalingPlan.id diff --git a/avm/res/desktop-virtualization/scaling-plan/main.json b/avm/res/desktop-virtualization/scaling-plan/main.json index f9f1af28c7..93bd78240d 100644 --- a/avm/res/desktop-virtualization/scaling-plan/main.json +++ b/avm/res/desktop-virtualization/scaling-plan/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "18153655960792051130" + "version": "0.26.54.24096", + "templateHash": "9815061252044383943" }, "name": "Azure Virtual Desktop Scaling Plan", "description": "This module deploys an Azure Virtual Desktop Scaling Plan.", diff --git a/avm/res/desktop-virtualization/scaling-plan/tests/e2e/defaults/main.test.bicep b/avm/res/desktop-virtualization/scaling-plan/tests/e2e/defaults/main.test.bicep index 1b45a81aec..532bc90df8 100644 --- a/avm/res/desktop-virtualization/scaling-plan/tests/e2e/defaults/main.test.bicep +++ b/avm/res/desktop-virtualization/scaling-plan/tests/e2e/defaults/main.test.bicep @@ -33,11 +33,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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}002' - location: resourceLocation +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + location: resourceLocation + } } -}] +] diff --git a/avm/res/desktop-virtualization/scaling-plan/tests/e2e/max/main.test.bicep b/avm/res/desktop-virtualization/scaling-plan/tests/e2e/max/main.test.bicep index 9a3224e186..a39813e0ff 100644 --- a/avm/res/desktop-virtualization/scaling-plan/tests/e2e/max/main.test.bicep +++ b/avm/res/desktop-virtualization/scaling-plan/tests/e2e/max/main.test.bicep @@ -57,167 +57,172 @@ 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}002' - location: resourceLocation - friendlyName: 'friendlyName' - description: 'myDescription' - schedules: [ - { - daysOfWeek: [ - 'Monday' - 'Wednesday' - 'Thursday' - 'Friday' - ] - name: 'WeekdaySchedule' - offPeakLoadBalancingAlgorithm: 'DepthFirst' - offPeakStartTime: { - hour: 20 - minute: 0 - } - peakLoadBalancingAlgorithm: 'DepthFirst' - peakStartTime: { - hour: 9 - minute: 0 - } - rampDownCapacityThresholdPct: 90 - rampDownForceLogoffUsers: true - rampDownLoadBalancingAlgorithm: 'DepthFirst' - rampDownMinimumHostsPct: 0 - rampDownNotificationMessage: 'You will be logged off in 30 min. Make sure to save your work.' - rampDownStartTime: { - hour: 18 - minute: 0 - } - rampDownStopHostsWhen: 'ZeroActiveSessions' - rampDownWaitTimeMinutes: 30 - rampUpCapacityThresholdPct: 80 - rampUpLoadBalancingAlgorithm: 'BreadthFirst' - rampUpMinimumHostsPct: 20 - rampUpStartTime: { - hour: 7 - minute: 0 +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + location: resourceLocation + friendlyName: 'friendlyName' + description: 'myDescription' + schedules: [ + { + daysOfWeek: [ + 'Monday' + 'Wednesday' + 'Thursday' + 'Friday' + ] + name: 'WeekdaySchedule' + offPeakLoadBalancingAlgorithm: 'DepthFirst' + offPeakStartTime: { + hour: 20 + minute: 0 + } + peakLoadBalancingAlgorithm: 'DepthFirst' + peakStartTime: { + hour: 9 + minute: 0 + } + rampDownCapacityThresholdPct: 90 + rampDownForceLogoffUsers: true + rampDownLoadBalancingAlgorithm: 'DepthFirst' + rampDownMinimumHostsPct: 0 + rampDownNotificationMessage: 'You will be logged off in 30 min. Make sure to save your work.' + rampDownStartTime: { + hour: 18 + minute: 0 + } + rampDownStopHostsWhen: 'ZeroActiveSessions' + rampDownWaitTimeMinutes: 30 + rampUpCapacityThresholdPct: 80 + rampUpLoadBalancingAlgorithm: 'BreadthFirst' + rampUpMinimumHostsPct: 20 + rampUpStartTime: { + hour: 7 + minute: 0 + } } - } - { - daysOfWeek: [ - 'Tuesday' - ] - name: 'weekdaysSchedule-agent-updates' - offPeakLoadBalancingAlgorithm: 'DepthFirst' - offPeakStartTime: { - hour: 20 - minute: 0 + { + daysOfWeek: [ + 'Tuesday' + ] + name: 'weekdaysSchedule-agent-updates' + offPeakLoadBalancingAlgorithm: 'DepthFirst' + offPeakStartTime: { + hour: 20 + minute: 0 + } + peakLoadBalancingAlgorithm: 'DepthFirst' + peakStartTime: { + hour: 9 + minute: 0 + } + rampDownCapacityThresholdPct: 90 + rampDownForceLogoffUsers: true + rampDownLoadBalancingAlgorithm: 'DepthFirst' + rampDownMinimumHostsPct: 0 + rampDownNotificationMessage: 'You will be logged off in 30 min. Make sure to save your work.' + rampDownStartTime: { + hour: 19 + minute: 0 + } + rampDownStopHostsWhen: 'ZeroActiveSessions' + rampDownWaitTimeMinutes: 30 + rampUpCapacityThresholdPct: 80 + rampUpLoadBalancingAlgorithm: 'BreadthFirst' + rampUpMinimumHostsPct: 20 + rampUpStartTime: { + hour: 7 + minute: 0 + } } - peakLoadBalancingAlgorithm: 'DepthFirst' - peakStartTime: { - hour: 9 - minute: 0 + { + daysOfWeek: [ + 'Saturday' + 'Sunday' + ] + name: 'WeekendSchedule' + offPeakLoadBalancingAlgorithm: 'DepthFirst' + offPeakStartTime: { + hour: 18 + minute: 0 + } + peakLoadBalancingAlgorithm: 'DepthFirst' + peakStartTime: { + hour: 10 + minute: 0 + } + rampDownCapacityThresholdPct: 90 + rampDownForceLogoffUsers: true + rampDownLoadBalancingAlgorithm: 'DepthFirst' + rampDownMinimumHostsPct: 0 + rampDownNotificationMessage: 'You will be logged off in 30 min. Make sure to save your work.' + rampDownStartTime: { + hour: 16 + minute: 0 + } + rampDownStopHostsWhen: 'ZeroActiveSessions' + rampDownWaitTimeMinutes: 30 + rampUpCapacityThresholdPct: 90 + rampUpLoadBalancingAlgorithm: 'DepthFirst' + rampUpMinimumHostsPct: 0 + rampUpStartTime: { + hour: 9 + minute: 0 + } } - rampDownCapacityThresholdPct: 90 - rampDownForceLogoffUsers: true - rampDownLoadBalancingAlgorithm: 'DepthFirst' - rampDownMinimumHostsPct: 0 - rampDownNotificationMessage: 'You will be logged off in 30 min. Make sure to save your work.' - rampDownStartTime: { - hour: 19 - minute: 0 + ] + hostPoolReferences: [ + { + hostPoolArmPath: nestedDependencies.outputs.hostPoolId + scalingPlanEnabled: true } - rampDownStopHostsWhen: 'ZeroActiveSessions' - rampDownWaitTimeMinutes: 30 - rampUpCapacityThresholdPct: 80 - rampUpLoadBalancingAlgorithm: 'BreadthFirst' - rampUpMinimumHostsPct: 20 - rampUpStartTime: { - hour: 7 - minute: 0 + ] + diagnosticSettings: [ + { + name: 'customSetting' + logCategoriesAndGroups: [ + { + categoryGroup: 'allLogs' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - daysOfWeek: [ - 'Saturday' - 'Sunday' - ] - name: 'WeekendSchedule' - offPeakLoadBalancingAlgorithm: 'DepthFirst' - offPeakStartTime: { - hour: 18 - minute: 0 - } - peakLoadBalancingAlgorithm: 'DepthFirst' - peakStartTime: { - hour: 10 - minute: 0 + roleAssignments: [ + { + roleDefinitionIdOrName: 'Owner' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' } - rampDownCapacityThresholdPct: 90 - rampDownForceLogoffUsers: true - rampDownLoadBalancingAlgorithm: 'DepthFirst' - rampDownMinimumHostsPct: 0 - rampDownNotificationMessage: 'You will be logged off in 30 min. Make sure to save your work.' - rampDownStartTime: { - hour: 16 - minute: 0 + { + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' } - rampDownStopHostsWhen: 'ZeroActiveSessions' - rampDownWaitTimeMinutes: 30 - rampUpCapacityThresholdPct: 90 - rampUpLoadBalancingAlgorithm: 'DepthFirst' - rampUpMinimumHostsPct: 0 - rampUpStartTime: { - hour: 9 - minute: 0 + { + 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' + Role: 'DeploymentValidation' } - ] - hostPoolReferences: [ - { - hostPoolArmPath: nestedDependencies.outputs.hostPoolId - scalingPlanEnabled: true - } - ] - diagnosticSettings: [ - { - name: 'customSetting' - logCategoriesAndGroups: [ - { - categoryGroup: 'allLogs' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - 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' - } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/desktop-virtualization/scaling-plan/tests/e2e/waf-aligned/main.test.bicep b/avm/res/desktop-virtualization/scaling-plan/tests/e2e/waf-aligned/main.test.bicep index 6d8d79a130..8e0f7bf7bc 100644 --- a/avm/res/desktop-virtualization/scaling-plan/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/desktop-virtualization/scaling-plan/tests/e2e/waf-aligned/main.test.bicep @@ -48,26 +48,28 @@ 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}002' - friendlyName: 'myFriendlyName' - location: resourceLocation - description: 'myDescription' - diagnosticSettings: [ - { - 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}002' + friendlyName: 'myFriendlyName' + location: resourceLocation + description: 'myDescription' + diagnosticSettings: [ + { + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/desktop-virtualization/workspace/main.bicep b/avm/res/desktop-virtualization/workspace/main.bicep index b696e0baca..06136befd9 100644 --- a/avm/res/desktop-virtualization/workspace/main.bicep +++ b/avm/res/desktop-virtualization/workspace/main.bicep @@ -60,23 +60,27 @@ var builtInRoleNames = { 'Desktop Virtualization Workspace Reader': '/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d' } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: take('46d3xbcp.res.desktopvirtualization-workspace.${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' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: take( + '46d3xbcp.res.desktopvirtualization-workspace.${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' + } } } } } -} resource workspace 'Microsoft.DesktopVirtualization/workspaces@2022-10-14-preview' = { name: name @@ -90,89 +94,108 @@ resource workspace 'Microsoft.DesktopVirtualization/workspaces@2022-10-14-previe } } -module workspace_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-Workspace-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(workspace.id, '/'))}-${privateEndpoint.?service ?? 'connection'}-${index}' - privateLinkServiceConnections: [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(workspace.id, '/'))}-${privateEndpoint.?service ?? 'connection'}-${index}' - properties: { - privateLinkServiceId: workspace.id - groupIds: [ - privateEndpoint.?service ?? 'connection' - ] +module workspace_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-Workspace-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(workspace.id, '/'))}-${privateEndpoint.?service ?? 'connection'}-${index}' + privateLinkServiceConnections: [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(workspace.id, '/'))}-${privateEndpoint.?service ?? 'connection'}-${index}' + properties: { + privateLinkServiceId: workspace.id + groupIds: [ + privateEndpoint.?service ?? 'connection' + ] + } } - } - ] - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(workspace.id, '/'))}-${privateEndpoint.?service ?? 'connection'}-${index}' - properties: { - privateLinkServiceId: workspace.id - groupIds: [ - privateEndpoint.?service ?? 'connection' + ] + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(workspace.id, '/'))}-${privateEndpoint.?service ?? 'connection'}-${index}' + properties: { + privateLinkServiceId: workspace.id + groupIds: [ + privateEndpoint.?service ?? 'connection' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] +] -resource workspace_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.' +resource workspace_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: workspace } - scope: workspace -} -resource workspace_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(workspace.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - principalId: roleAssignment.principalId - description: roleAssignment.?description - principalType: roleAssignment.?principalType - condition: roleAssignment.?condition - conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null - delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId +resource workspace_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(workspace.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + principalId: roleAssignment.principalId + description: roleAssignment.?description + principalType: roleAssignment.?principalType + condition: roleAssignment.?condition + conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null + delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId + } + scope: workspace } - scope: workspace -}] +] -resource workspace_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - logs: diagnosticSetting.?logCategoriesAndGroups ?? [ - { - categoryGroup: 'allLogs' - enabled: true - } - ] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource workspace_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + logs: diagnosticSetting.?logCategoriesAndGroups ?? [ + { + categoryGroup: 'allLogs' + enabled: true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: workspace } - scope: workspace -}] +] @sys.description('The resource ID of the workspace.') output resourceId string = workspace.id diff --git a/avm/res/desktop-virtualization/workspace/main.json b/avm/res/desktop-virtualization/workspace/main.json index 504dc0dc06..fafa2032d3 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.25.53.49325", - "templateHash": "1061929067377896447" + "version": "0.26.54.24096", + "templateHash": "15344364678225245703" }, "name": "Workspace", "description": "This module deploys an Azure Virtual Desktop Workspace.", diff --git a/avm/res/desktop-virtualization/workspace/tests/e2e/defaults/main.test.bicep b/avm/res/desktop-virtualization/workspace/tests/e2e/defaults/main.test.bicep index 4fe2615c0e..f990891507 100644 --- a/avm/res/desktop-virtualization/workspace/tests/e2e/defaults/main.test.bicep +++ b/avm/res/desktop-virtualization/workspace/tests/e2e/defaults/main.test.bicep @@ -33,11 +33,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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}002' - location: resourceLocation +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + location: resourceLocation + } } -}] +] diff --git a/avm/res/desktop-virtualization/workspace/tests/e2e/max/main.test.bicep b/avm/res/desktop-virtualization/workspace/tests/e2e/max/main.test.bicep index e81a1febd0..4ba1325da5 100644 --- a/avm/res/desktop-virtualization/workspace/tests/e2e/max/main.test.bicep +++ b/avm/res/desktop-virtualization/workspace/tests/e2e/max/main.test.bicep @@ -58,128 +58,133 @@ 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 - applicationGroupReferences: [] - friendlyName: 'AVD Workspace' - publicNetworkAccess: 'Disabled' - diagnosticSettings: [ - { - name: 'customSetting' - logCategoriesAndGroups: [ - { - categoryGroup: 'allLogs' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - 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' - } - ] - privateEndpoints: [ - { - service: 'feed' - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +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 + applicationGroupReferences: [] + friendlyName: 'AVD Workspace' + publicNetworkAccess: 'Disabled' + diagnosticSettings: [ + { + name: 'customSetting' + logCategoriesAndGroups: [ + { + categoryGroup: 'allLogs' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + roleAssignments: [ + { + roleDefinitionIdOrName: 'Owner' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + { + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + privateEndpoints: [ + { + service: 'feed' + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - ipConfigurations: [ - { - name: 'myIPconfig-feed1' - properties: { - groupId: 'feed' - memberName: 'web-r0' - privateIPAddress: '10.0.0.10' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' } - } - { - name: 'myIPconfig-feed2' - properties: { - groupId: 'feed' - memberName: 'web-r1' - privateIPAddress: '10.0.0.13' + ] + ipConfigurations: [ + { + name: 'myIPconfig-feed1' + properties: { + groupId: 'feed' + memberName: 'web-r0' + privateIPAddress: '10.0.0.10' + } } - } - ] - customDnsConfigs: [] - } - { - service: 'global' - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + { + name: 'myIPconfig-feed2' + properties: { + groupId: 'feed' + memberName: 'web-r1' + privateIPAddress: '10.0.0.13' + } + } + ] + customDnsConfigs: [] } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + { + service: 'global' + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - ipConfigurations: [ - { - name: 'myIPconfig-global' - properties: { - groupId: 'global' - memberName: 'web' - privateIPAddress: '10.0.0.11' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' } - } - ] - customDnsConfigs: [] + ] + ipConfigurations: [ + { + name: 'myIPconfig-global' + properties: { + groupId: 'global' + memberName: 'web' + privateIPAddress: '10.0.0.11' + } + } + ] + customDnsConfigs: [] + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/desktop-virtualization/workspace/tests/e2e/waf-aligned/main.test.bicep b/avm/res/desktop-virtualization/workspace/tests/e2e/waf-aligned/main.test.bicep index 1103178216..0d560ab307 100644 --- a/avm/res/desktop-virtualization/workspace/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/desktop-virtualization/workspace/tests/e2e/waf-aligned/main.test.bicep @@ -48,27 +48,29 @@ 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}002' - location: resourceLocation - diagnosticSettings: [ - { - 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}002' + location: resourceLocation + diagnosticSettings: [ + { + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + diagnosticDependencies + ] } - dependsOn: [ - diagnosticDependencies - ] -}] +] diff --git a/avm/res/dev-test-lab/lab/artifactsource/main.json b/avm/res/dev-test-lab/lab/artifactsource/main.json index f1effe1d6d..be320c82ec 100644 --- a/avm/res/dev-test-lab/lab/artifactsource/main.json +++ b/avm/res/dev-test-lab/lab/artifactsource/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "15843038393934364114" + "version": "0.26.54.24096", + "templateHash": "11935479410507680738" }, "name": "DevTest Lab Artifact Sources", "description": "This module deploys a DevTest Lab Artifact Source.\n\nAn artifact source allows you to create custom artifacts for the VMs in the lab, or use Azure Resource Manager templates to create a custom test environment. You must add a private Git repository for the artifacts or Resource Manager templates that your team creates. The repository can be hosted on GitHub or on Azure DevOps Services.", diff --git a/avm/res/dev-test-lab/lab/cost/main.json b/avm/res/dev-test-lab/lab/cost/main.json index 594f4bf22a..725ab01ee8 100644 --- a/avm/res/dev-test-lab/lab/cost/main.json +++ b/avm/res/dev-test-lab/lab/cost/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "65674909664804563" + "version": "0.26.54.24096", + "templateHash": "11267524415855336246" }, "name": "DevTest Lab Costs", "description": "This module deploys a DevTest Lab Cost.\n\nManage lab costs by setting a spending target that can be viewed in the Monthly Estimated Cost Trend chart. DevTest Labs can send a notification when spending reaches the specified target threshold.", diff --git a/avm/res/dev-test-lab/lab/main.bicep b/avm/res/dev-test-lab/lab/main.bicep index fb53d16685..58763e05dd 100644 --- a/avm/res/dev-test-lab/lab/main.bicep +++ b/avm/res/dev-test-lab/lab/main.bicep @@ -114,43 +114,67 @@ param costs object = {} @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -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: !empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned' - userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null -} : any(null) +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: !empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned' + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null + } + : any(null) -var formattedManagementIdentities = !empty(managementIdentitiesResourceIds) ? reduce(map((managementIdentitiesResourceIds ?? []), (id) => { '${id}': {} }), {}, (cur, next) => union(cur, next)) : {} // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } +var formattedManagementIdentities = !empty(managementIdentitiesResourceIds) + ? reduce(map((managementIdentitiesResourceIds ?? []), (id) => { '${id}': {} }), {}, (cur, next) => union(cur, next)) + : {} // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'DevTest Labs User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '76283e04-6283-4c54-8f91-bcf1374a3c64' + ) Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') - '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') - 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Resource Policy Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '36243c78-bf99-498c-9df9-86d9f8d28608' + ) + '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' + ) + 'Virtual Machine Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '9980e02c-c2be-4d73-94e8-173b1dc7cf3c' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.devtestlab-lab.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.devtestlab-lab.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource lab 'Microsoft.DevTestLab/labs@2018-10-15-preview' = { name: name @@ -179,128 +203,176 @@ resource lab 'Microsoft.DevTestLab/labs@2018-10-15-preview' = { } } -resource lab_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.' +resource lab_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: lab } - scope: lab -} -module lab_virtualNetworks 'virtualnetwork/main.bicep' = [for (virtualNetwork, index) in virtualnetworks: { - name: '${uniqueString(deployment().name, location)}-Lab-VirtualNetwork-${index}' - params: { - labName: lab.name - name: virtualNetwork.name - tags: virtualNetwork.?tags ?? tags - externalProviderResourceId: virtualNetwork.externalProviderResourceId - description: contains(virtualNetwork, 'description') ? virtualNetwork.description : '' - allowedSubnets: contains(virtualNetwork, 'allowedSubnets') ? virtualNetwork.allowedSubnets : [] - subnetOverrides: contains(virtualNetwork, 'subnetOverrides') ? virtualNetwork.subnetOverrides : [] +module lab_virtualNetworks 'virtualnetwork/main.bicep' = [ + for (virtualNetwork, index) in virtualnetworks: { + name: '${uniqueString(deployment().name, location)}-Lab-VirtualNetwork-${index}' + params: { + labName: lab.name + name: virtualNetwork.name + tags: virtualNetwork.?tags ?? tags + externalProviderResourceId: virtualNetwork.externalProviderResourceId + description: contains(virtualNetwork, 'description') ? virtualNetwork.description : '' + allowedSubnets: contains(virtualNetwork, 'allowedSubnets') ? virtualNetwork.allowedSubnets : [] + subnetOverrides: contains(virtualNetwork, 'subnetOverrides') ? virtualNetwork.subnetOverrides : [] + } } -}] - -module lab_policies 'policyset/policy/main.bicep' = [for (policy, index) in policies: { - name: '${uniqueString(deployment().name, location)}-Lab-PolicySets-Policy-${index}' - params: { - labName: lab.name - name: policy.name - - description: contains(policy, 'description') ? policy.description : '' - evaluatorType: policy.evaluatorType - factData: contains(policy, 'factData') ? policy.factData : '' - factName: policy.factName - status: contains(policy, 'status') ? policy.status : 'Enabled' - threshold: policy.threshold +] + +module lab_policies 'policyset/policy/main.bicep' = [ + for (policy, index) in policies: { + name: '${uniqueString(deployment().name, location)}-Lab-PolicySets-Policy-${index}' + params: { + labName: lab.name + name: policy.name + + description: contains(policy, 'description') ? policy.description : '' + evaluatorType: policy.evaluatorType + factData: contains(policy, 'factData') ? policy.factData : '' + factName: policy.factName + status: contains(policy, 'status') ? policy.status : 'Enabled' + threshold: policy.threshold + } } -}] - -module lab_schedules 'schedule/main.bicep' = [for (schedule, index) in schedules: { - name: '${uniqueString(deployment().name, location)}-Lab-Schedules-${index}' - params: { - labName: lab.name - name: schedule.name - tags: schedule.?tags ?? tags - taskType: schedule.taskType - dailyRecurrence: contains(schedule, 'dailyRecurrence') ? schedule.dailyRecurrence : {} - hourlyRecurrence: contains(schedule, 'hourlyRecurrence') ? schedule.hourlyRecurrence : {} - weeklyRecurrence: contains(schedule, 'weeklyRecurrence') ? schedule.weeklyRecurrence : {} - status: contains(schedule, 'status') ? schedule.status : 'Enabled' - targetResourceId: contains(schedule, 'targetResourceId') ? schedule.targetResourceId : '' - timeZoneId: contains(schedule, 'timeZoneId') ? schedule.timeZoneId : 'Pacific Standard time' - notificationSettingsStatus: contains(schedule, 'notificationSettingsStatus') ? schedule.notificationSettingsStatus : 'Disabled' - notificationSettingsTimeInMinutes: contains(schedule, 'notificationSettingsTimeInMinutes') ? schedule.notificationSettingsTimeInMinutes : 30 +] + +module lab_schedules 'schedule/main.bicep' = [ + for (schedule, index) in schedules: { + name: '${uniqueString(deployment().name, location)}-Lab-Schedules-${index}' + params: { + labName: lab.name + name: schedule.name + tags: schedule.?tags ?? tags + taskType: schedule.taskType + dailyRecurrence: contains(schedule, 'dailyRecurrence') ? schedule.dailyRecurrence : {} + hourlyRecurrence: contains(schedule, 'hourlyRecurrence') ? schedule.hourlyRecurrence : {} + weeklyRecurrence: contains(schedule, 'weeklyRecurrence') ? schedule.weeklyRecurrence : {} + status: contains(schedule, 'status') ? schedule.status : 'Enabled' + targetResourceId: contains(schedule, 'targetResourceId') ? schedule.targetResourceId : '' + timeZoneId: contains(schedule, 'timeZoneId') ? schedule.timeZoneId : 'Pacific Standard time' + notificationSettingsStatus: contains(schedule, 'notificationSettingsStatus') + ? schedule.notificationSettingsStatus + : 'Disabled' + notificationSettingsTimeInMinutes: contains(schedule, 'notificationSettingsTimeInMinutes') + ? schedule.notificationSettingsTimeInMinutes + : 30 + } } -}] - -module lab_notificationChannels 'notificationchannel/main.bicep' = [for (notificationChannel, index) in notificationchannels: { - name: '${uniqueString(deployment().name, location)}-Lab-NotificationChannels-${index}' - params: { - labName: lab.name - name: notificationChannel.name - tags: notificationChannel.?tags ?? tags - description: contains(notificationChannel, 'description') ? notificationChannel.description : '' - events: notificationChannel.events - emailRecipient: contains(notificationChannel, 'emailRecipient') ? notificationChannel.emailRecipient : '' - webHookUrl: contains(notificationChannel, 'webhookUrl') ? notificationChannel.webhookUrl : '' - notificationLocale: contains(notificationChannel, 'notificationLocale') ? notificationChannel.notificationLocale : 'en' +] + +module lab_notificationChannels 'notificationchannel/main.bicep' = [ + for (notificationChannel, index) in notificationchannels: { + name: '${uniqueString(deployment().name, location)}-Lab-NotificationChannels-${index}' + params: { + labName: lab.name + name: notificationChannel.name + tags: notificationChannel.?tags ?? tags + description: contains(notificationChannel, 'description') ? notificationChannel.description : '' + events: notificationChannel.events + emailRecipient: contains(notificationChannel, 'emailRecipient') ? notificationChannel.emailRecipient : '' + webHookUrl: contains(notificationChannel, 'webhookUrl') ? notificationChannel.webhookUrl : '' + notificationLocale: contains(notificationChannel, 'notificationLocale') + ? notificationChannel.notificationLocale + : 'en' + } } -}] - -module lab_artifactSources 'artifactsource/main.bicep' = [for (artifactSource, index) in artifactsources: { - name: '${uniqueString(deployment().name, location)}-Lab-ArtifactSources-${index}' - params: { - labName: lab.name - name: artifactSource.name - tags: artifactSource.?tags ?? tags - displayName: contains(artifactSource, 'displayName') ? artifactSource.displayName : artifactSource.name - branchRef: contains(artifactSource, 'branchRef') ? artifactSource.branchRef : '' - folderPath: contains(artifactSource, 'folderPath') ? artifactSource.folderPath : '' - armTemplateFolderPath: contains(artifactSource, 'armTemplateFolderPath') ? artifactSource.armTemplateFolderPath : '' - sourceType: contains(artifactSource, 'sourceType') ? artifactSource.sourceType : '' - status: contains(artifactSource, 'status') ? artifactSource.status : 'Enabled' - uri: artifactSource.uri +] + +module lab_artifactSources 'artifactsource/main.bicep' = [ + for (artifactSource, index) in artifactsources: { + name: '${uniqueString(deployment().name, location)}-Lab-ArtifactSources-${index}' + params: { + labName: lab.name + name: artifactSource.name + tags: artifactSource.?tags ?? tags + displayName: contains(artifactSource, 'displayName') ? artifactSource.displayName : artifactSource.name + branchRef: contains(artifactSource, 'branchRef') ? artifactSource.branchRef : '' + folderPath: contains(artifactSource, 'folderPath') ? artifactSource.folderPath : '' + armTemplateFolderPath: contains(artifactSource, 'armTemplateFolderPath') + ? artifactSource.armTemplateFolderPath + : '' + sourceType: contains(artifactSource, 'sourceType') ? artifactSource.sourceType : '' + status: contains(artifactSource, 'status') ? artifactSource.status : 'Enabled' + uri: artifactSource.uri + } } -}] - -module lab_costs 'cost/main.bicep' = if (!empty(costs)) { - name: '${uniqueString(deployment().name, location)}-Lab-Costs' - params: { - labName: lab.name - tags: costs.?tags ?? tags - currencyCode: contains(costs, 'currencyCode') ? costs.currencyCode : 'USD' - cycleType: costs.cycleType - cycleStartDateTime: contains(costs, 'cycleStartDateTime') ? costs.cycleStartDateTime : '' - cycleEndDateTime: contains(costs, 'cycleEndDateTime') ? costs.cycleEndDateTime : '' - status: contains(costs, 'status') ? costs.status : 'Enabled' - target: contains(costs, 'target') ? costs.target : 0 - thresholdValue25DisplayOnChart: contains(costs, 'thresholdValue25DisplayOnChart') ? costs.thresholdValue25DisplayOnChart : 'Disabled' - thresholdValue25SendNotificationWhenExceeded: contains(costs, 'thresholdValue25SendNotificationWhenExceeded') ? costs.thresholdValue25SendNotificationWhenExceeded : 'Disabled' - thresholdValue50DisplayOnChart: contains(costs, 'thresholdValue50DisplayOnChart') ? costs.thresholdValue50DisplayOnChart : 'Disabled' - thresholdValue50SendNotificationWhenExceeded: contains(costs, 'thresholdValue50SendNotificationWhenExceeded') ? costs.thresholdValue50SendNotificationWhenExceeded : 'Disabled' - thresholdValue75DisplayOnChart: contains(costs, 'thresholdValue75DisplayOnChart') ? costs.thresholdValue75DisplayOnChart : 'Disabled' - thresholdValue75SendNotificationWhenExceeded: contains(costs, 'thresholdValue75SendNotificationWhenExceeded') ? costs.thresholdValue75SendNotificationWhenExceeded : 'Disabled' - thresholdValue100DisplayOnChart: contains(costs, 'thresholdValue100DisplayOnChart') ? costs.thresholdValue100DisplayOnChart : 'Disabled' - thresholdValue100SendNotificationWhenExceeded: contains(costs, 'thresholdValue100SendNotificationWhenExceeded') ? costs.thresholdValue100SendNotificationWhenExceeded : 'Disabled' - thresholdValue125DisplayOnChart: contains(costs, 'thresholdValue125DisplayOnChart') ? costs.thresholdValue125DisplayOnChart : 'Disabled' - thresholdValue125SendNotificationWhenExceeded: contains(costs, 'thresholdValue125SendNotificationWhenExceeded') ? costs.thresholdValue125SendNotificationWhenExceeded : 'Disabled' +] + +module lab_costs 'cost/main.bicep' = + if (!empty(costs)) { + name: '${uniqueString(deployment().name, location)}-Lab-Costs' + params: { + labName: lab.name + tags: costs.?tags ?? tags + currencyCode: contains(costs, 'currencyCode') ? costs.currencyCode : 'USD' + cycleType: costs.cycleType + cycleStartDateTime: contains(costs, 'cycleStartDateTime') ? costs.cycleStartDateTime : '' + cycleEndDateTime: contains(costs, 'cycleEndDateTime') ? costs.cycleEndDateTime : '' + status: contains(costs, 'status') ? costs.status : 'Enabled' + target: contains(costs, 'target') ? costs.target : 0 + thresholdValue25DisplayOnChart: contains(costs, 'thresholdValue25DisplayOnChart') + ? costs.thresholdValue25DisplayOnChart + : 'Disabled' + thresholdValue25SendNotificationWhenExceeded: contains(costs, 'thresholdValue25SendNotificationWhenExceeded') + ? costs.thresholdValue25SendNotificationWhenExceeded + : 'Disabled' + thresholdValue50DisplayOnChart: contains(costs, 'thresholdValue50DisplayOnChart') + ? costs.thresholdValue50DisplayOnChart + : 'Disabled' + thresholdValue50SendNotificationWhenExceeded: contains(costs, 'thresholdValue50SendNotificationWhenExceeded') + ? costs.thresholdValue50SendNotificationWhenExceeded + : 'Disabled' + thresholdValue75DisplayOnChart: contains(costs, 'thresholdValue75DisplayOnChart') + ? costs.thresholdValue75DisplayOnChart + : 'Disabled' + thresholdValue75SendNotificationWhenExceeded: contains(costs, 'thresholdValue75SendNotificationWhenExceeded') + ? costs.thresholdValue75SendNotificationWhenExceeded + : 'Disabled' + thresholdValue100DisplayOnChart: contains(costs, 'thresholdValue100DisplayOnChart') + ? costs.thresholdValue100DisplayOnChart + : 'Disabled' + thresholdValue100SendNotificationWhenExceeded: contains(costs, 'thresholdValue100SendNotificationWhenExceeded') + ? costs.thresholdValue100SendNotificationWhenExceeded + : 'Disabled' + thresholdValue125DisplayOnChart: contains(costs, 'thresholdValue125DisplayOnChart') + ? costs.thresholdValue125DisplayOnChart + : 'Disabled' + thresholdValue125SendNotificationWhenExceeded: contains(costs, 'thresholdValue125SendNotificationWhenExceeded') + ? costs.thresholdValue125SendNotificationWhenExceeded + : 'Disabled' + } } -} -resource lab_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(lab.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource lab_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(lab.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: lab } - scope: lab -}] +] @description('The unique identifier for the lab. Used to track tags that the lab applies to each resource that it creates.') output uniqueIdentifier string = lab.properties.uniqueIdentifier diff --git a/avm/res/dev-test-lab/lab/main.json b/avm/res/dev-test-lab/lab/main.json index cf21fa30b3..8fff71a8e5 100644 --- a/avm/res/dev-test-lab/lab/main.json +++ b/avm/res/dev-test-lab/lab/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "7675513612588492913" + "version": "0.26.54.24096", + "templateHash": "7819268743072339084" }, "name": "DevTest Labs", "description": "This module deploys a DevTest Lab.", @@ -486,8 +486,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "418188724139628409" + "version": "0.26.54.24096", + "templateHash": "6899804233871456970" }, "name": "DevTest Lab Virtual Networks", "description": "This module deploys a DevTest Lab Virtual Network.\n\nLab virtual machines must be deployed into a virtual network. This resource type allows configuring the virtual network and subnet settings used for the lab virtual machines.", @@ -632,8 +632,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16570135700722429091" + "version": "0.26.54.24096", + "templateHash": "486340638220018026" }, "name": "DevTest Lab Policy Sets Policies", "description": "This module deploys a DevTest Lab Policy Sets Policy.\n\nDevTest lab policies are used to modify the lab settings such as only allowing certain VM Size SKUs, marketplace image types, number of VMs allowed per user and other settings.", @@ -798,8 +798,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "96187176657838206" + "version": "0.26.54.24096", + "templateHash": "5684619798703415484" }, "name": "DevTest Lab Schedules", "description": "This module deploys a DevTest Lab Schedule.\n\nLab schedules are used to modify the settings for auto-shutdown, auto-start for lab virtual machines.", @@ -998,8 +998,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "18438352233682084029" + "version": "0.26.54.24096", + "templateHash": "1696945877581040577" }, "name": "DevTest Lab Notification Channels", "description": "This module deploys a DevTest Lab Notification Channel.\n\nNotification channels are used by the schedule resource type in order to send notifications or events to email addresses and/or webhooks.", @@ -1158,8 +1158,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "15843038393934364114" + "version": "0.26.54.24096", + "templateHash": "11935479410507680738" }, "name": "DevTest Lab Artifact Sources", "description": "This module deploys a DevTest Lab Artifact Source.\n\nAn artifact source allows you to create custom artifacts for the VMs in the lab, or use Azure Resource Manager templates to create a custom test environment. You must add a private Git repository for the artifacts or Resource Manager templates that your team creates. The repository can be hosted on GitHub or on Azure DevOps Services.", @@ -1350,8 +1350,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "65674909664804563" + "version": "0.26.54.24096", + "templateHash": "11267524415855336246" }, "name": "DevTest Lab Costs", "description": "This module deploys a DevTest Lab Cost.\n\nManage lab costs by setting a spending target that can be viewed in the Monthly Estimated Cost Trend chart. DevTest Labs can send a notification when spending reaches the specified target threshold.", diff --git a/avm/res/dev-test-lab/lab/notificationchannel/main.json b/avm/res/dev-test-lab/lab/notificationchannel/main.json index 8310fa785d..8d69509f11 100644 --- a/avm/res/dev-test-lab/lab/notificationchannel/main.json +++ b/avm/res/dev-test-lab/lab/notificationchannel/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "18438352233682084029" + "version": "0.26.54.24096", + "templateHash": "1696945877581040577" }, "name": "DevTest Lab Notification Channels", "description": "This module deploys a DevTest Lab Notification Channel.\n\nNotification channels are used by the schedule resource type in order to send notifications or events to email addresses and/or webhooks.", diff --git a/avm/res/dev-test-lab/lab/policyset/policy/main.json b/avm/res/dev-test-lab/lab/policyset/policy/main.json index 42085fd964..6da1dd875f 100644 --- a/avm/res/dev-test-lab/lab/policyset/policy/main.json +++ b/avm/res/dev-test-lab/lab/policyset/policy/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16570135700722429091" + "version": "0.26.54.24096", + "templateHash": "486340638220018026" }, "name": "DevTest Lab Policy Sets Policies", "description": "This module deploys a DevTest Lab Policy Sets Policy.\n\nDevTest lab policies are used to modify the lab settings such as only allowing certain VM Size SKUs, marketplace image types, number of VMs allowed per user and other settings.", diff --git a/avm/res/dev-test-lab/lab/schedule/main.bicep b/avm/res/dev-test-lab/lab/schedule/main.bicep index e3ae7dcd60..c71be08e40 100644 --- a/avm/res/dev-test-lab/lab/schedule/main.bicep +++ b/avm/res/dev-test-lab/lab/schedule/main.bicep @@ -72,10 +72,12 @@ resource schedule 'Microsoft.DevTestLab/labs/schedules@2018-09-15' = { status: status targetResourceId: !empty(targetResourceId) ? targetResourceId : null timeZoneId: timeZoneId - notificationSettings: notificationSettingsStatus == 'Enabled' ? { - status: notificationSettingsStatus - timeInMinutes: notificationSettingsTimeInMinutes - } : {} + notificationSettings: notificationSettingsStatus == 'Enabled' + ? { + status: notificationSettingsStatus + timeInMinutes: notificationSettingsTimeInMinutes + } + : {} } } diff --git a/avm/res/dev-test-lab/lab/schedule/main.json b/avm/res/dev-test-lab/lab/schedule/main.json index 859cb7f806..be1257f81e 100644 --- a/avm/res/dev-test-lab/lab/schedule/main.json +++ b/avm/res/dev-test-lab/lab/schedule/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "96187176657838206" + "version": "0.26.54.24096", + "templateHash": "5684619798703415484" }, "name": "DevTest Lab Schedules", "description": "This module deploys a DevTest Lab Schedule.\n\nLab schedules are used to modify the settings for auto-shutdown, auto-start for lab virtual machines.", diff --git a/avm/res/dev-test-lab/lab/tests/e2e/defaults/main.test.bicep b/avm/res/dev-test-lab/lab/tests/e2e/defaults/main.test.bicep index 92ab727db0..429a4ed306 100644 --- a/avm/res/dev-test-lab/lab/tests/e2e/defaults/main.test.bicep +++ b/avm/res/dev-test-lab/lab/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 +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 + } } -}] +] diff --git a/avm/res/dev-test-lab/lab/tests/e2e/max/dependencies.bicep b/avm/res/dev-test-lab/lab/tests/e2e/max/dependencies.bicep index 10d28c8ae6..376758c41c 100644 --- a/avm/res/dev-test-lab/lab/tests/e2e/max/dependencies.bicep +++ b/avm/res/dev-test-lab/lab/tests/e2e/max/dependencies.bicep @@ -71,7 +71,10 @@ resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { scope: keyVault properties: { principalId: diskEncryptionSet.identity.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6') // Key Vault Crypto Service Encryption User + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'e147488a-f6f5-4113-8e2d-b22465e65bf6' + ) // Key Vault Crypto Service Encryption User principalType: 'ServicePrincipal' } } diff --git a/avm/res/dev-test-lab/lab/tests/e2e/max/main.test.bicep b/avm/res/dev-test-lab/lab/tests/e2e/max/main.test.bicep index 3f6526a8cd..898647489d 100644 --- a/avm/res/dev-test-lab/lab/tests/e2e/max/main.test.bicep +++ b/avm/res/dev-test-lab/lab/tests/e2e/max/main.test.bicep @@ -53,242 +53,247 @@ 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: resourceGroup.location - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - 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' +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: resourceGroup.location + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - resourceType: 'DevTest Lab' - labName: '${namePrefix}${serviceShort}001' - } - announcement: { - enabled: 'Enabled' - expirationDate: '2028-12-30T13:00:00.000Z' - markdown: 'DevTest Lab announcement text.
New line. It also supports Markdown' - title: 'DevTest announcement title' - } - environmentPermission: 'Contributor' - extendedProperties: { - RdpConnectionType: '7' - } - labStorageType: 'Premium' - artifactsStorageAccount: nestedDependencies.outputs.storageAccountResourceId - premiumDataDisks: 'Enabled' - support: { - enabled: 'Enabled' - markdown: 'DevTest Lab support text.
New line. It also supports Markdown' - } - managedIdentities: { - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId + 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' + } ] - } - managementIdentitiesResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - vmCreationResourceGroupId: resourceGroup.id - browserConnect: 'Enabled' - disableAutoUpgradeCseMinorVersion: true - isolateLabResources: 'Enabled' - encryptionType: 'EncryptionAtRestWithCustomerKey' - encryptionDiskEncryptionSetId: nestedDependencies.outputs.diskEncryptionSetResourceId - virtualnetworks: [ - { - name: nestedDependencies.outputs.virtualNetworkName - externalProviderResourceId: nestedDependencies.outputs.virtualNetworkResourceId - description: 'lab virtual network description' - allowedSubnets: [ - { - labSubnetName: nestedDependencies.outputs.subnetName - resourceId: nestedDependencies.outputs.subnetResourceId - allowPublicIp: 'Allow' - } - ] - subnetOverrides: [ - { - labSubnetName: nestedDependencies.outputs.subnetName - resourceId: nestedDependencies.outputs.subnetResourceId - useInVmCreationPermission: 'Allow' - usePublicIpAddressPermission: 'Allow' - sharedPublicIpAddressConfiguration: { - allowedPorts: [ - { - transportProtocol: 'Tcp' - backendPort: 3389 - } - { - transportProtocol: 'Tcp' - backendPort: 22 - } - ] - } - } - ] - } - ] - policies: [ - { - name: nestedDependencies.outputs.subnetName - evaluatorType: 'MaxValuePolicy' - factData: nestedDependencies.outputs.subnetResourceId - factName: 'UserOwnedLabVmCountInSubnet' - threshold: '1' - } - { - name: 'MaxVmsAllowedPerUser' - evaluatorType: 'MaxValuePolicy' - factName: 'UserOwnedLabVmCount' - threshold: '2' - } - { - name: 'MaxPremiumVmsAllowedPerUser' - evaluatorType: 'MaxValuePolicy' - factName: 'UserOwnedLabPremiumVmCount' - status: 'Disabled' - threshold: '1' - } - { - name: 'MaxVmsAllowedPerLab' - evaluatorType: 'MaxValuePolicy' - factName: 'LabVmCount' - threshold: '3' - } - { - name: 'MaxPremiumVmsAllowedPerLab' - evaluatorType: 'MaxValuePolicy' - factName: 'LabPremiumVmCount' - threshold: '2' - } - { - name: 'AllowedVmSizesInLab' - evaluatorType: 'AllowedValuesPolicy' - factData: '' - factName: 'LabVmSize' - threshold: ' ${string('["Basic_A0","Basic_A1"]')}' - status: 'Enabled' + tags: { + 'hidden-title': 'This is visible in the resource name' + resourceType: 'DevTest Lab' + labName: '${namePrefix}${serviceShort}001' } - { - name: 'ScheduleEditPermission' - evaluatorType: 'AllowedValuesPolicy' - factName: 'ScheduleEditPermission' - threshold: ' ${string('["None","Modify"]')}' + announcement: { + enabled: 'Enabled' + expirationDate: '2028-12-30T13:00:00.000Z' + markdown: 'DevTest Lab announcement text.
New line. It also supports Markdown' + title: 'DevTest announcement title' } - { - name: 'GalleryImage' - evaluatorType: 'AllowedValuesPolicy' - factName: 'GalleryImage' - threshold: ' ${string('["{\\"offer\\":\\"WindowsServer\\",\\"publisher\\":\\"MicrosoftWindowsServer\\",\\"sku\\":\\"2019-Datacenter-smalldisk\\",\\"osType\\":\\"Windows\\",\\"version\\":\\"latest\\"}","{\\"offer\\":\\"WindowsServer\\",\\"publisher\\":\\"MicrosoftWindowsServer\\",\\"sku\\":\\"2022-datacenter-smalldisk\\",\\"osType\\":\\"Windows\\",\\"version\\":\\"latest\\"}"]')}' + environmentPermission: 'Contributor' + extendedProperties: { + RdpConnectionType: '7' } - { - name: 'EnvironmentTemplate' - description: 'Public Environment Policy' - evaluatorType: 'AllowedValuesPolicy' - factName: 'EnvironmentTemplate' - threshold: ' ${string('[""]')}' + labStorageType: 'Premium' + artifactsStorageAccount: nestedDependencies.outputs.storageAccountResourceId + premiumDataDisks: 'Enabled' + support: { + enabled: 'Enabled' + markdown: 'DevTest Lab support text.
New line. It also supports Markdown' } - ] - schedules: [ - { - name: 'LabVmsShutdown' - taskType: 'LabVmsShutdownTask' - status: 'Enabled' - timeZoneId: 'AUS Eastern Standard Time' - dailyRecurrence: { - time: '0000' - } - notificationSettingsStatus: 'Enabled' - notificationSettingsTimeInMinutes: 30 + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] } - { - name: 'LabVmAutoStart' - taskType: 'LabVmsStartupTask' - status: 'Enabled' - timeZoneId: 'AUS Eastern Standard Time' - weeklyRecurrence: { - time: '0700' - weekdays: [ - 'Monday' - 'Tuesday' - 'Wednesday' - 'Thursday' - 'Friday' + managementIdentitiesResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + vmCreationResourceGroupId: resourceGroup.id + browserConnect: 'Enabled' + disableAutoUpgradeCseMinorVersion: true + isolateLabResources: 'Enabled' + encryptionType: 'EncryptionAtRestWithCustomerKey' + encryptionDiskEncryptionSetId: nestedDependencies.outputs.diskEncryptionSetResourceId + virtualnetworks: [ + { + name: nestedDependencies.outputs.virtualNetworkName + externalProviderResourceId: nestedDependencies.outputs.virtualNetworkResourceId + description: 'lab virtual network description' + allowedSubnets: [ + { + labSubnetName: nestedDependencies.outputs.subnetName + resourceId: nestedDependencies.outputs.subnetResourceId + allowPublicIp: 'Allow' + } + ] + subnetOverrides: [ + { + labSubnetName: nestedDependencies.outputs.subnetName + resourceId: nestedDependencies.outputs.subnetResourceId + useInVmCreationPermission: 'Allow' + usePublicIpAddressPermission: 'Allow' + sharedPublicIpAddressConfiguration: { + allowedPorts: [ + { + transportProtocol: 'Tcp' + backendPort: 3389 + } + { + transportProtocol: 'Tcp' + backendPort: 22 + } + ] + } + } ] } - } - ] - notificationchannels: [ - { - name: 'autoShutdown' - description: 'Integration configured for auto-shutdown' - events: [ - { - eventName: 'AutoShutdown' + ] + policies: [ + { + name: nestedDependencies.outputs.subnetName + evaluatorType: 'MaxValuePolicy' + factData: nestedDependencies.outputs.subnetResourceId + factName: 'UserOwnedLabVmCountInSubnet' + threshold: '1' + } + { + name: 'MaxVmsAllowedPerUser' + evaluatorType: 'MaxValuePolicy' + factName: 'UserOwnedLabVmCount' + threshold: '2' + } + { + name: 'MaxPremiumVmsAllowedPerUser' + evaluatorType: 'MaxValuePolicy' + factName: 'UserOwnedLabPremiumVmCount' + status: 'Disabled' + threshold: '1' + } + { + name: 'MaxVmsAllowedPerLab' + evaluatorType: 'MaxValuePolicy' + factName: 'LabVmCount' + threshold: '3' + } + { + name: 'MaxPremiumVmsAllowedPerLab' + evaluatorType: 'MaxValuePolicy' + factName: 'LabPremiumVmCount' + threshold: '2' + } + { + name: 'AllowedVmSizesInLab' + evaluatorType: 'AllowedValuesPolicy' + factData: '' + factName: 'LabVmSize' + threshold: ' ${string('["Basic_A0","Basic_A1"]')}' + status: 'Enabled' + } + { + name: 'ScheduleEditPermission' + evaluatorType: 'AllowedValuesPolicy' + factName: 'ScheduleEditPermission' + threshold: ' ${string('["None","Modify"]')}' + } + { + name: 'GalleryImage' + evaluatorType: 'AllowedValuesPolicy' + factName: 'GalleryImage' + threshold: ' ${string('["{\\"offer\\":\\"WindowsServer\\",\\"publisher\\":\\"MicrosoftWindowsServer\\",\\"sku\\":\\"2019-Datacenter-smalldisk\\",\\"osType\\":\\"Windows\\",\\"version\\":\\"latest\\"}","{\\"offer\\":\\"WindowsServer\\",\\"publisher\\":\\"MicrosoftWindowsServer\\",\\"sku\\":\\"2022-datacenter-smalldisk\\",\\"osType\\":\\"Windows\\",\\"version\\":\\"latest\\"}"]')}' + } + { + name: 'EnvironmentTemplate' + description: 'Public Environment Policy' + evaluatorType: 'AllowedValuesPolicy' + factName: 'EnvironmentTemplate' + threshold: ' ${string('[""]')}' + } + ] + schedules: [ + { + name: 'LabVmsShutdown' + taskType: 'LabVmsShutdownTask' + status: 'Enabled' + timeZoneId: 'AUS Eastern Standard Time' + dailyRecurrence: { + time: '0000' } - ] - emailRecipient: 'mail@contosodtlmail.com' - webHookUrl: 'https://webhook.contosotest.com' - notificationLocale: 'en' - } - { - name: 'costThreshold' - events: [ - { - eventName: 'Cost' + notificationSettingsStatus: 'Enabled' + notificationSettingsTimeInMinutes: 30 + } + { + name: 'LabVmAutoStart' + taskType: 'LabVmsStartupTask' + status: 'Enabled' + timeZoneId: 'AUS Eastern Standard Time' + weeklyRecurrence: { + time: '0700' + weekdays: [ + 'Monday' + 'Tuesday' + 'Wednesday' + 'Thursday' + 'Friday' + ] } - ] - webHookUrl: 'https://webhook.contosotest.com' - } - ] - artifactsources: [ - { - name: 'Public Repo' - displayName: 'Public Artifact Repo' - status: 'Disabled' - uri: 'https://github.com/Azure/azure-devtestlab.git' - sourceType: 'GitHub' - branchRef: 'master' - folderPath: '/Artifacts' - } - { - name: 'Public Environment Repo' - displayName: 'Public Environment Repo' - status: 'Disabled' - uri: 'https://github.com/Azure/azure-devtestlab.git' - sourceType: 'GitHub' - branchRef: 'master' - armTemplateFolderPath: '/Environments' + } + ] + notificationchannels: [ + { + name: 'autoShutdown' + description: 'Integration configured for auto-shutdown' + events: [ + { + eventName: 'AutoShutdown' + } + ] + emailRecipient: 'mail@contosodtlmail.com' + webHookUrl: 'https://webhook.contosotest.com' + notificationLocale: 'en' + } + { + name: 'costThreshold' + events: [ + { + eventName: 'Cost' + } + ] + webHookUrl: 'https://webhook.contosotest.com' + } + ] + artifactsources: [ + { + name: 'Public Repo' + displayName: 'Public Artifact Repo' + status: 'Disabled' + uri: 'https://github.com/Azure/azure-devtestlab.git' + sourceType: 'GitHub' + branchRef: 'master' + folderPath: '/Artifacts' + } + { + name: 'Public Environment Repo' + displayName: 'Public Environment Repo' + status: 'Disabled' + uri: 'https://github.com/Azure/azure-devtestlab.git' + sourceType: 'GitHub' + branchRef: 'master' + armTemplateFolderPath: '/Environments' + } + ] + costs: { + status: 'Enabled' + cycleType: 'CalendarMonth' + target: 450 + thresholdValue100DisplayOnChart: 'Enabled' + thresholdValue100SendNotificationWhenExceeded: 'Enabled' } - ] - costs: { - status: 'Enabled' - cycleType: 'CalendarMonth' - target: 450 - thresholdValue100DisplayOnChart: 'Enabled' - thresholdValue100SendNotificationWhenExceeded: 'Enabled' } } -}] +] diff --git a/avm/res/dev-test-lab/lab/tests/e2e/waf-aligned/main.test.bicep b/avm/res/dev-test-lab/lab/tests/e2e/waf-aligned/main.test.bicep index e7af1bbad9..3ecf9f9e52 100644 --- a/avm/res/dev-test-lab/lab/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/dev-test-lab/lab/tests/e2e/waf-aligned/main.test.bicep @@ -46,16 +46,18 @@ 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: resourceGroup.location - tags: { - 'hidden-title': 'This is visible in the resource name' - resourceType: 'DevTest Lab' - labName: '${namePrefix}${serviceShort}001' +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: resourceGroup.location + tags: { + 'hidden-title': 'This is visible in the resource name' + resourceType: 'DevTest Lab' + labName: '${namePrefix}${serviceShort}001' + } } } -}] +] diff --git a/avm/res/dev-test-lab/lab/virtualnetwork/main.json b/avm/res/dev-test-lab/lab/virtualnetwork/main.json index 4af584e570..7e9745af75 100644 --- a/avm/res/dev-test-lab/lab/virtualnetwork/main.json +++ b/avm/res/dev-test-lab/lab/virtualnetwork/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "418188724139628409" + "version": "0.26.54.24096", + "templateHash": "6899804233871456970" }, "name": "DevTest Lab Virtual Networks", "description": "This module deploys a DevTest Lab Virtual Network.\n\nLab virtual machines must be deployed into a virtual network. This resource type allows configuring the virtual network and subnet settings used for the lab virtual machines.", diff --git a/avm/res/event-grid/domain/main.bicep b/avm/res/event-grid/domain/main.bicep index 2b02292287..6c5936bf8c 100644 --- a/avm/res/event-grid/domain/main.bicep +++ b/avm/res/event-grid/domain/main.bicep @@ -52,42 +52,72 @@ param managedIdentities managedIdentitiesType @description('Optional. Allow only Azure AD authentication. Should be enabled for security reasons.') param disableLocalAuth bool = true -var formattedUserAssignedIdentities = reduce(map((managedIdentities.?userAssignedResourcesIds ?? []), (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.?userAssignedResourcesIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(managedIdentities.?userAssignedResourcesIds ?? {}) ? 'UserAssigned' : null) - userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null -} : null +var formattedUserAssignedIdentities = reduce( + map((managedIdentities.?userAssignedResourcesIds ?? []), (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.?userAssignedResourcesIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') + : (!empty(managedIdentities.?userAssignedResourcesIds ?? {}) ? 'UserAssigned' : null) + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null + } + : null var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'EventGrid Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1e241071-0855-49ea-94dc-649edcd759de') - 'EventGrid Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7') - 'EventGrid EventSubscription Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443') - 'EventGrid EventSubscription Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405') + 'EventGrid Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '1e241071-0855-49ea-94dc-649edcd759de' + ) + 'EventGrid Data Sender': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'd5a91429-5739-47e2-a06b-3470a27159e7' + ) + 'EventGrid EventSubscription Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '428e0ff0-5e57-4d9c-a221-2c70d0e0a443' + ) + 'EventGrid EventSubscription Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '2414bbcf-6497-4faf-8c65-045460748405' + ) 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') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: take('46d3xbcp.res.eventgrid-domain.${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' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: take( + '46d3xbcp.res.eventgrid-domain.${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' + } } } } } -} resource domain 'Microsoft.EventGrid/domains@2023-06-01-preview' = { name: name @@ -95,7 +125,9 @@ resource domain 'Microsoft.EventGrid/domains@2023-06-01-preview' = { tags: tags identity: identity properties: { - publicNetworkAccess: !empty(publicNetworkAccess) ? any(publicNetworkAccess) : (!empty(privateEndpoints) && empty(inboundIpRules) ? 'Disabled' : null) + publicNetworkAccess: !empty(publicNetworkAccess) + ? any(publicNetworkAccess) + : (!empty(privateEndpoints) && empty(inboundIpRules) ? 'Disabled' : null) inboundIpRules: !empty(inboundIpRules) ? inboundIpRules : null autoCreateTopicWithFirstSubscription: autoCreateTopicWithFirstSubscription autoDeleteTopicWithLastSubscription: autoDeleteTopicWithLastSubscription @@ -103,101 +135,126 @@ resource domain 'Microsoft.EventGrid/domains@2023-06-01-preview' = { } } -module domain_topics 'topic/main.bicep' = [for (topic, index) in (topics ?? []): { - name: '${uniqueString(deployment().name, location)}-topics-${index}' - params: { - domainName: domain.name - name: topic +module domain_topics 'topic/main.bicep' = [ + for (topic, index) in (topics ?? []): { + name: '${uniqueString(deployment().name, location)}-topics-${index}' + params: { + domainName: domain.name + name: topic + } } -}] +] -resource domain_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.' +resource domain_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: domain } - scope: domain -} -resource domain_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource domain_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: domain } - scope: domain -}] - -module domain_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-Domain-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(domain.id, '/'))}-${privateEndpoint.?service ?? 'domain'}-${index}' - privateLinkServiceConnections: [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(domain.id, '/'))}-${privateEndpoint.?service ?? 'domain'}-${index}' - properties: { - privateLinkServiceId: domain.id - groupIds: [ - privateEndpoint.?service ?? 'domain' - ] +] + +module domain_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-Domain-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(domain.id, '/'))}-${privateEndpoint.?service ?? 'domain'}-${index}' + privateLinkServiceConnections: [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(domain.id, '/'))}-${privateEndpoint.?service ?? 'domain'}-${index}' + properties: { + privateLinkServiceId: domain.id + groupIds: [ + privateEndpoint.?service ?? 'domain' + ] + } } - } - ] - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(domain.id, '/'))}-${privateEndpoint.?service ?? 'domain'}-${index}' - properties: { - privateLinkServiceId: domain.id - groupIds: [ - privateEndpoint.?service ?? 'domain' + ] + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(domain.id, '/'))}-${privateEndpoint.?service ?? 'domain'}-${index}' + properties: { + privateLinkServiceId: domain.id + groupIds: [ + privateEndpoint.?service ?? 'domain' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] +] -resource domain_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(domain.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource domain_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(domain.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: domain } - scope: domain -}] +] @description('The name of the event grid domain.') output name string = domain.name diff --git a/avm/res/event-grid/domain/main.json b/avm/res/event-grid/domain/main.json index 287a5989c6..06df4dfe5e 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.25.53.49325", - "templateHash": "7406933903897002331" + "version": "0.26.54.24096", + "templateHash": "5443849158463047514" }, "name": "Event Grid Domains", "description": "This module deploys an Event Grid Domain.", @@ -692,8 +692,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3346602576302560002" + "version": "0.26.54.24096", + "templateHash": "11448955001407567896" }, "name": "Event Grid Domain Topics", "description": "This module deploys an Event Grid Domain Topic.", diff --git a/avm/res/event-grid/domain/tests/e2e/defaults/main.test.bicep b/avm/res/event-grid/domain/tests/e2e/defaults/main.test.bicep index f60f9071a1..4ef73b4322 100644 --- a/avm/res/event-grid/domain/tests/e2e/defaults/main.test.bicep +++ b/avm/res/event-grid/domain/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 +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 + } } -}] +] diff --git a/avm/res/event-grid/domain/tests/e2e/max/main.test.bicep b/avm/res/event-grid/domain/tests/e2e/max/main.test.bicep index 8e80b695fd..eb86e5c6ea 100644 --- a/avm/res/event-grid/domain/tests/e2e/max/main.test.bicep +++ b/avm/res/event-grid/domain/tests/e2e/max/main.test.bicep @@ -60,83 +60,88 @@ 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 - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - inboundIpRules: [ - { - action: 'Allow' - ipMask: '40.74.28.0/23' - } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +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 + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } + ] + inboundIpRules: [ + { + action: 'Allow' + ipMask: '40.74.28.0/23' + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - subnetResourceId: 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' + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + topics: [ + '${namePrefix}-topic-${serviceShort}001' + ] } - topics: [ - '${namePrefix}-topic-${serviceShort}001' + dependsOn: [ + nestedDependencies + diagnosticDependencies ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/event-grid/domain/tests/e2e/waf-aligned/main.test.bicep b/avm/res/event-grid/domain/tests/e2e/waf-aligned/main.test.bicep index 17923ede99..6f5ed2bdbd 100644 --- a/avm/res/event-grid/domain/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/event-grid/domain/tests/e2e/waf-aligned/main.test.bicep @@ -59,56 +59,58 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t // 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 - 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 + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + inboundIpRules: [] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - inboundIpRules: [] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - service: 'domain' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + service: 'domain' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + topics: [ + '${namePrefix}-topic-${serviceShort}001' + ] } - topics: [ - '${namePrefix}-topic-${serviceShort}001' + dependsOn: [ + nestedDependencies + diagnosticDependencies ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/event-grid/domain/topic/main.json b/avm/res/event-grid/domain/topic/main.json index 2d26a76f82..c9e6632c2e 100644 --- a/avm/res/event-grid/domain/topic/main.json +++ b/avm/res/event-grid/domain/topic/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3346602576302560002" + "version": "0.26.54.24096", + "templateHash": "11448955001407567896" }, "name": "Event Grid Domain Topics", "description": "This module deploys an Event Grid Domain Topic.", diff --git a/avm/res/event-grid/namespace/ca-certificate/main.json b/avm/res/event-grid/namespace/ca-certificate/main.json index 16e7ad0345..47fa8d0ce2 100644 --- a/avm/res/event-grid/namespace/ca-certificate/main.json +++ b/avm/res/event-grid/namespace/ca-certificate/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "13620127830367721222" + "version": "0.26.54.24096", + "templateHash": "1062917273000341959" }, "name": "Eventgrid Namespace CA Certificates", "description": "This module deploys an Eventgrid Namespace CA Certificate.", diff --git a/avm/res/event-grid/namespace/client-group/main.json b/avm/res/event-grid/namespace/client-group/main.json index 125c0311f0..5e393fa85d 100644 --- a/avm/res/event-grid/namespace/client-group/main.json +++ b/avm/res/event-grid/namespace/client-group/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "10781129401411225399" + "version": "0.26.54.24096", + "templateHash": "7182498673501513186" }, "name": "Eventgrid Namespace Client Groups", "description": "This module deploys an Eventgrid Namespace Client Group.", diff --git a/avm/res/event-grid/namespace/client/main.bicep b/avm/res/event-grid/namespace/client/main.bicep index f327199c31..044864b850 100644 --- a/avm/res/event-grid/namespace/client/main.bicep +++ b/avm/res/event-grid/namespace/client/main.bicep @@ -17,14 +17,13 @@ param description string? param authenticationName string? @sys.allowed([ - 'DnsMatchesAuthenticationName' - 'EmailMatchesAuthenticationName' - 'IpMatchesAuthenticationName' - 'SubjectMatchesAuthenticationName' - 'ThumbprintMatch' - 'UriMatchesAuthenticationName' - ] -) + 'DnsMatchesAuthenticationName' + 'EmailMatchesAuthenticationName' + 'IpMatchesAuthenticationName' + 'SubjectMatchesAuthenticationName' + 'ThumbprintMatch' + 'UriMatchesAuthenticationName' +]) @sys.description('Optional. The validation scheme used to authenticate the client.') param clientCertificateAuthenticationValidationSchema string = 'SubjectMatchesAuthenticationName' @@ -54,7 +53,9 @@ resource client 'Microsoft.EventGrid/namespaces/clients@2023-12-15-preview' = { attributes: attributes clientCertificateAuthentication: { validationScheme: clientCertificateAuthenticationValidationSchema - allowedThumbprints: clientCertificateAuthenticationValidationSchema == 'ThumbprintMatch' ? clientCertificateAuthenticationAllowedThumbprints : null + allowedThumbprints: clientCertificateAuthenticationValidationSchema == 'ThumbprintMatch' + ? clientCertificateAuthenticationAllowedThumbprints + : null } state: state } diff --git a/avm/res/event-grid/namespace/client/main.json b/avm/res/event-grid/namespace/client/main.json index 0e0d7c7227..26f45c3c04 100644 --- a/avm/res/event-grid/namespace/client/main.json +++ b/avm/res/event-grid/namespace/client/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "10531114495322688171" + "version": "0.26.54.24096", + "templateHash": "11296609826875033958" }, "name": "Eventgrid Namespace Clients", "description": "This module deploys an Eventgrid Namespace Client.", diff --git a/avm/res/event-grid/namespace/main.bicep b/avm/res/event-grid/namespace/main.bicep index d2b2581705..247475ff32 100644 --- a/avm/res/event-grid/namespace/main.bicep +++ b/avm/res/event-grid/namespace/main.bicep @@ -99,50 +99,89 @@ param topicSpaces array? @description('Optional. All namespace Permission Bindings to create. Used only when MQTT broker is enabled (\'topicSpacesState\' is set to \'Enabled\').') param permissionBindings array? -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' : 'None') - userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null -} : null +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' : 'None') + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null + } + : null var builtInRoleNames = { - 'Azure Resource Notifications System Topics Subscriber': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0b962ed2-6d56-471c-bd5f-3477d83a7ba4') + 'Azure Resource Notifications System Topics Subscriber': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '0b962ed2-6d56-471c-bd5f-3477d83a7ba4' + ) Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'EventGrid Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1e241071-0855-49ea-94dc-649edcd759de') - 'EventGrid Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d8c3fe3-8864-474b-8749-01e3783e8157') - 'EventGrid Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '78cbd9e7-9798-4e2e-9b5a-547d9ebb31fb') - 'EventGrid Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7') - 'EventGrid EventSubscription Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443') - 'EventGrid EventSubscription Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405') - 'EventGrid TopicSpaces Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a12b0b94-b317-4dcd-84a8-502ce99884c6') - 'EventGrid TopicSpaces Subscriber': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4b0f2fd7-60b4-4eca-896f-4435034f8bf5') + 'EventGrid Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '1e241071-0855-49ea-94dc-649edcd759de' + ) + 'EventGrid Data Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '1d8c3fe3-8864-474b-8749-01e3783e8157' + ) + 'EventGrid Data Receiver': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '78cbd9e7-9798-4e2e-9b5a-547d9ebb31fb' + ) + 'EventGrid Data Sender': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'd5a91429-5739-47e2-a06b-3470a27159e7' + ) + 'EventGrid EventSubscription Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '428e0ff0-5e57-4d9c-a221-2c70d0e0a443' + ) + 'EventGrid EventSubscription Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '2414bbcf-6497-4faf-8c65-045460748405' + ) + 'EventGrid TopicSpaces Publisher': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'a12b0b94-b317-4dcd-84a8-502ce99884c6' + ) + 'EventGrid TopicSpaces Subscriber': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '4b0f2fd7-60b4-4eca-896f-4435034f8bf5' + ) Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'User Access Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + ) } // ============== // // Resources // // ============== // -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.eventgrid-namespace.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.eventgrid-namespace.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource namespace 'Microsoft.EventGrid/namespaces@2023-12-15-preview' = { name: name @@ -151,183 +190,231 @@ resource namespace 'Microsoft.EventGrid/namespaces@2023-12-15-preview' = { identity: identity properties: { isZoneRedundant: isZoneRedundant - publicNetworkAccess: !empty(publicNetworkAccess) ? publicNetworkAccess : (!empty(privateEndpoints) ? 'Disabled' : 'Enabled') + publicNetworkAccess: !empty(publicNetworkAccess) + ? publicNetworkAccess + : (!empty(privateEndpoints) ? 'Disabled' : 'Enabled') inboundIpRules: inboundIpRules - topicSpacesConfiguration: topicSpacesState == 'Enabled' ? { - state: topicSpacesState - clientAuthentication: !empty(alternativeAuthenticationNameSources) ? { - alternativeAuthenticationNameSources: alternativeAuthenticationNameSources - } : null - maximumSessionExpiryInHours: maximumSessionExpiryInHours - maximumClientSessionsPerAuthenticationName: maximumClientSessionsPerAuthenticationName - routeTopicResourceId: routeTopicResourceId - routingEnrichments: !empty(routeTopicResourceId) ? routingEnrichments : null - routingIdentityInfo: !empty(routeTopicResourceId) && !startsWith(routeTopicResourceId ?? '', '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.EventGrid/namespaces/${name}/topics/') ? routingIdentityInfo : null // Use routingIdentityInfo only if the topic is not in the same namespace - } : null + topicSpacesConfiguration: topicSpacesState == 'Enabled' + ? { + state: topicSpacesState + clientAuthentication: !empty(alternativeAuthenticationNameSources) + ? { + alternativeAuthenticationNameSources: alternativeAuthenticationNameSources + } + : null + maximumSessionExpiryInHours: maximumSessionExpiryInHours + maximumClientSessionsPerAuthenticationName: maximumClientSessionsPerAuthenticationName + routeTopicResourceId: routeTopicResourceId + routingEnrichments: !empty(routeTopicResourceId) ? routingEnrichments : null + routingIdentityInfo: !empty(routeTopicResourceId) && !startsWith( + routeTopicResourceId ?? '', + '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.EventGrid/namespaces/${name}/topics/' + ) + ? routingIdentityInfo + : null // Use routingIdentityInfo only if the topic is not in the same namespace + } + : null } } -resource namespace_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.' +resource namespace_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: namespace } - scope: namespace -} -resource namespace_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource namespace_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: namespace } - scope: namespace -}] - -module namespace_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.1' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-namespace-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(namespace.id, '/'))}-${privateEndpoint.?service ?? 'topic'}-${index}' - privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(namespace.id, '/'))}-${privateEndpoint.?service ?? 'topic'}-${index}' - properties: { - privateLinkServiceId: namespace.id - groupIds: [ - privateEndpoint.?service ?? 'topic' +] + +module namespace_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.1' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-namespace-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(namespace.id, '/'))}-${privateEndpoint.?service ?? 'topic'}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(namespace.id, '/'))}-${privateEndpoint.?service ?? 'topic'}-${index}' + properties: { + privateLinkServiceId: namespace.id + groupIds: [ + privateEndpoint.?service ?? 'topic' + ] + } + } ] - } - } - ] : null - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(namespace.id, '/'))}-${privateEndpoint.?service ?? 'topic'}-${index}' - properties: { - privateLinkServiceId: namespace.id - groupIds: [ - privateEndpoint.?service ?? 'topic' + : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(namespace.id, '/'))}-${privateEndpoint.?service ?? 'topic'}-${index}' + properties: { + privateLinkServiceId: namespace.id + groupIds: [ + privateEndpoint.?service ?? 'topic' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] +] -resource namespace_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(namespace.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource namespace_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(namespace.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: namespace } - scope: namespace -}] - -module namespace_topics 'topic/main.bicep' = [for (topic, index) in (topics ?? []): { - name: '${uniqueString(deployment().name, location)}-Namespace-Topic-${index}' - params: { - name: topic.name - namespaceName: namespace.name - eventRetentionInDays: topic.?eventRetentionInDays - inputSchema: topic.?inputSchema - publisherType: topic.?publisherType - roleAssignments: topic.?roleAssignments - eventSubscriptions: topic.?eventSubscriptions +] + +module namespace_topics 'topic/main.bicep' = [ + for (topic, index) in (topics ?? []): { + name: '${uniqueString(deployment().name, location)}-Namespace-Topic-${index}' + params: { + name: topic.name + namespaceName: namespace.name + eventRetentionInDays: topic.?eventRetentionInDays + inputSchema: topic.?inputSchema + publisherType: topic.?publisherType + roleAssignments: topic.?roleAssignments + eventSubscriptions: topic.?eventSubscriptions + } } -}] - -module namespace_caCertificates 'ca-certificate/main.bicep' = [for (caCertificate, index) in (caCertificates ?? []): if (topicSpacesState == 'Enabled') { - name: '${uniqueString(deployment().name, location)}-Namespace-caCertificate-${index}' - params: { - name: caCertificate.name - namespaceName: namespace.name - description: caCertificate.?description - encodedCertificate: caCertificate.encodedCertificate +] + +module namespace_caCertificates 'ca-certificate/main.bicep' = [ + for (caCertificate, index) in (caCertificates ?? []): if (topicSpacesState == 'Enabled') { + name: '${uniqueString(deployment().name, location)}-Namespace-caCertificate-${index}' + params: { + name: caCertificate.name + namespaceName: namespace.name + description: caCertificate.?description + encodedCertificate: caCertificate.encodedCertificate + } } -}] - -module namespace_clients 'client/main.bicep' = [for (client, index) in (clients ?? []): if (topicSpacesState == 'Enabled') { - name: '${uniqueString(deployment().name, location)}-Namespace-Client-${index}' - params: { - name: client.name - namespaceName: namespace.name - authenticationName: client.?authenticationName - description: client.?description - clientCertificateAuthenticationValidationSchema: client.?clientCertificateAuthenticationValidationSchema - clientCertificateAuthenticationAllowedThumbprints: client.?clientCertificateAuthenticationAllowedThumbprints - attributes: client.?attributes - state: client.?state +] + +module namespace_clients 'client/main.bicep' = [ + for (client, index) in (clients ?? []): if (topicSpacesState == 'Enabled') { + name: '${uniqueString(deployment().name, location)}-Namespace-Client-${index}' + params: { + name: client.name + namespaceName: namespace.name + authenticationName: client.?authenticationName + description: client.?description + clientCertificateAuthenticationValidationSchema: client.?clientCertificateAuthenticationValidationSchema + clientCertificateAuthenticationAllowedThumbprints: client.?clientCertificateAuthenticationAllowedThumbprints + attributes: client.?attributes + state: client.?state + } } -}] - -module namespace_clientGroups 'client-group/main.bicep' = [for (clientGroup, index) in (clientGroups ?? []): if (topicSpacesState == 'Enabled') { - name: '${uniqueString(deployment().name, location)}-Namespace-clientGroup-${index}' - params: { - name: clientGroup.name - namespaceName: namespace.name - query: clientGroup.query - description: clientGroup.?description +] + +module namespace_clientGroups 'client-group/main.bicep' = [ + for (clientGroup, index) in (clientGroups ?? []): if (topicSpacesState == 'Enabled') { + name: '${uniqueString(deployment().name, location)}-Namespace-clientGroup-${index}' + params: { + name: clientGroup.name + namespaceName: namespace.name + query: clientGroup.query + description: clientGroup.?description + } } -}] - -module namespace_topicSpaces 'topic-space/main.bicep' = [for (topicSpaces, index) in (topicSpaces ?? []): if (topicSpacesState == 'Enabled') { - name: '${uniqueString(deployment().name, location)}-Namespace-topicSpace-${index}' - params: { - name: topicSpaces.name - namespaceName: namespace.name - description: topicSpaces.?description - topicTemplates: topicSpaces.topicTemplates - roleAssignments: topicSpaces.?roleAssignments +] + +module namespace_topicSpaces 'topic-space/main.bicep' = [ + for (topicSpaces, index) in (topicSpaces ?? []): if (topicSpacesState == 'Enabled') { + name: '${uniqueString(deployment().name, location)}-Namespace-topicSpace-${index}' + params: { + name: topicSpaces.name + namespaceName: namespace.name + description: topicSpaces.?description + topicTemplates: topicSpaces.topicTemplates + roleAssignments: topicSpaces.?roleAssignments + } } -}] - -module namespace_permissionBindings 'permission-binding/main.bicep' = [for (permissionBinding, index) in (permissionBindings ?? []): if (topicSpacesState == 'Enabled') { - name: '${uniqueString(deployment().name, location)}-Namespace-permissionBinding-${index}' - params: { - name: permissionBinding.name - namespaceName: namespace.name - description: permissionBinding.?description - clientGroupName: permissionBinding.clientGroupName - topicSpaceName: permissionBinding.topicSpaceName - permission: permissionBinding.permission +] + +module namespace_permissionBindings 'permission-binding/main.bicep' = [ + for (permissionBinding, index) in (permissionBindings ?? []): if (topicSpacesState == 'Enabled') { + name: '${uniqueString(deployment().name, location)}-Namespace-permissionBinding-${index}' + params: { + name: permissionBinding.name + namespaceName: namespace.name + description: permissionBinding.?description + clientGroupName: permissionBinding.clientGroupName + topicSpaceName: permissionBinding.topicSpaceName + permission: permissionBinding.permission + } + dependsOn: [ + namespace_clientGroups + namespace_topicSpaces + ] } - dependsOn: [ - namespace_clientGroups - namespace_topicSpaces - ] -}] +] // ============ // // Outputs // @@ -349,7 +436,9 @@ output resourceGroupName string = resourceGroup().name output systemAssignedMIPrincipalId string = namespace.?identity.?principalId ?? '' @sys.description('The Resources IDs of the EventGrid Namespace Topics.') -output topicResourceIds array = [for index in range(0, length(topics ?? [])): namespace_topics[index].outputs.resourceId] +output topicResourceIds array = [ + for index in range(0, length(topics ?? [])): namespace_topics[index].outputs.resourceId +] // ================ // // Definitions // diff --git a/avm/res/event-grid/namespace/main.json b/avm/res/event-grid/namespace/main.json index 61a0e2a060..e472645f36 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.25.53.49325", - "templateHash": "6122431651057596356" + "version": "0.26.54.24096", + "templateHash": "15037334455961343668" }, "name": "Event Grid Namespaces", "description": "This module deploys an Event Grid Namespace.", @@ -1458,8 +1458,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2836208779363789051" + "version": "0.26.54.24096", + "templateHash": "4459336414537252998" }, "name": "Eventgrid Namespace Topics", "description": "This module deploys an Eventgrid Namespace Topic.", @@ -1730,8 +1730,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "13130499975324434363" + "version": "0.26.54.24096", + "templateHash": "18248314164362964337" }, "name": "Event Subscriptions", "description": "This module deploys an Event Subscription.", @@ -2016,8 +2016,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "13620127830367721222" + "version": "0.26.54.24096", + "templateHash": "1062917273000341959" }, "name": "Eventgrid Namespace CA Certificates", "description": "This module deploys an Eventgrid Namespace CA Certificate.", @@ -2146,8 +2146,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "10531114495322688171" + "version": "0.26.54.24096", + "templateHash": "11296609826875033958" }, "name": "Eventgrid Namespace Clients", "description": "This module deploys an Eventgrid Namespace Client.", @@ -2312,8 +2312,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "10781129401411225399" + "version": "0.26.54.24096", + "templateHash": "7182498673501513186" }, "name": "Eventgrid Namespace Client Groups", "description": "This module deploys an Eventgrid Namespace Client Group.", @@ -2433,8 +2433,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "6548696237893842735" + "version": "0.26.54.24096", + "templateHash": "4931718668767892926" }, "name": "Eventgrid Namespace Topic Spaces", "description": "This module deploys an Eventgrid Namespace Topic Space.", @@ -2671,8 +2671,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "5622068529761827218" + "version": "0.26.54.24096", + "templateHash": "353917243244046230" }, "name": "Eventgrid Namespace Permissions Bindings", "description": "This module deploys an Eventgrid Namespace Permission Binding.", diff --git a/avm/res/event-grid/namespace/permission-binding/main.json b/avm/res/event-grid/namespace/permission-binding/main.json index 066199c338..2c4f60f516 100644 --- a/avm/res/event-grid/namespace/permission-binding/main.json +++ b/avm/res/event-grid/namespace/permission-binding/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "5622068529761827218" + "version": "0.26.54.24096", + "templateHash": "353917243244046230" }, "name": "Eventgrid Namespace Permissions Bindings", "description": "This module deploys an Eventgrid Namespace Permission Binding.", diff --git a/avm/res/event-grid/namespace/tests/e2e/defaults/main.test.bicep b/avm/res/event-grid/namespace/tests/e2e/defaults/main.test.bicep index b616ea7110..49bb45bff3 100644 --- a/avm/res/event-grid/namespace/tests/e2e/defaults/main.test.bicep +++ b/avm/res/event-grid/namespace/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 +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 + } } -}] +] diff --git a/avm/res/event-grid/namespace/tests/e2e/max/dependencies.bicep b/avm/res/event-grid/namespace/tests/e2e/max/dependencies.bicep index f2d9cb0e70..6ee87f960d 100644 --- a/avm/res/event-grid/namespace/tests/e2e/max/dependencies.bicep +++ b/avm/res/event-grid/namespace/tests/e2e/max/dependencies.bicep @@ -74,7 +74,10 @@ resource eventHubNamespaceRbacAssignment 'Microsoft.Authorization/roleAssignment name: guid(managedIdentity.id, 'evhrbacAssignment') scope: eventHubNamespace properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2b629674-e913-4c01-ae53-ef4638d8f975') // Azure Event Hubs Data Sender + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '2b629674-e913-4c01-ae53-ef4638d8f975' + ) // Azure Event Hubs Data Sender principalId: managedIdentity.properties.principalId principalType: 'ServicePrincipal' } diff --git a/avm/res/event-grid/namespace/tests/e2e/max/main.test.bicep b/avm/res/event-grid/namespace/tests/e2e/max/main.test.bicep index 69d432f2a6..bc7f73489c 100644 --- a/avm/res/event-grid/namespace/tests/e2e/max/main.test.bicep +++ b/avm/res/event-grid/namespace/tests/e2e/max/main.test.bicep @@ -62,183 +62,194 @@ 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 - managedIdentities: { - systemAssigned: true - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - privateEndpoints: [ - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId +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 + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId ] } - ] - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - 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 + } + ] + privateEndpoints: [ + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + } + ] + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - topics: [ - { - name: 'topic1' - eventRetentionInDays: 7 - eventSubscriptions: [ - { - name: 'subscription1' - 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' - } - ] - deliveryConfiguration: { - deliveryMode: 'Queue' - queue: { - receiveLockDurationInSeconds: 60 - maxDeliveryCount: 10 - eventTimeToLive: 'P7D' + topics: [ + { + name: 'topic1' + eventRetentionInDays: 7 + eventSubscriptions: [ + { + name: 'subscription1' + 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' + } + ] + deliveryConfiguration: { + deliveryMode: 'Queue' + queue: { + receiveLockDurationInSeconds: 60 + maxDeliveryCount: 10 + eventTimeToLive: 'P7D' + } } } - } - { - name: 'subscription2' - deliveryConfiguration: { - deliveryMode: 'Push' - push: { - maxDeliveryCount: 10 - eventTimeToLive: 'P7D' - deliveryWithResourceIdentity: { - identity: { - type: 'UserAssigned' - userAssignedIdentity: nestedDependencies.outputs.managedIdentityResourceId - } - destination: { - endpointType: 'EventHub' - properties: { - resourceId: nestedDependencies.outputs.eventHubResourceId - deliveryAttributeMappings: [ - { - properties: { - value: 'staticVaule' - isSecret: false + { + name: 'subscription2' + deliveryConfiguration: { + deliveryMode: 'Push' + push: { + maxDeliveryCount: 10 + eventTimeToLive: 'P7D' + deliveryWithResourceIdentity: { + identity: { + type: 'UserAssigned' + userAssignedIdentity: nestedDependencies.outputs.managedIdentityResourceId + } + destination: { + endpointType: 'EventHub' + properties: { + resourceId: nestedDependencies.outputs.eventHubResourceId + deliveryAttributeMappings: [ + { + properties: { + value: 'staticVaule' + isSecret: false + } + name: 'StaticHeader1' + type: 'Static' } - name: 'StaticHeader1' - type: 'Static' - } - { - properties: { - sourceField: 'id' + { + properties: { + sourceField: 'id' + } + name: 'DynamicHeader1' + type: 'Dynamic' } - name: 'DynamicHeader1' - type: 'Dynamic' - } - { - properties: { - value: 'Hidden' - isSecret: true + { + properties: { + value: 'Hidden' + isSecret: true + } + name: 'StaticSecretHeader1' + type: 'Static' } - name: 'StaticSecretHeader1' - type: 'Static' - } - ] + ] + } } } } } } + ] + } + { + name: 'topic2' + 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' + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - } - { - name: 'topic2' - 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' - } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' } - } - ] + ] + } } -}] +] diff --git a/avm/res/event-grid/namespace/tests/e2e/mqttct/dependencies.bicep b/avm/res/event-grid/namespace/tests/e2e/mqttct/dependencies.bicep index d3c4a66d2a..0edd63c133 100644 --- a/avm/res/event-grid/namespace/tests/e2e/mqttct/dependencies.bicep +++ b/avm/res/event-grid/namespace/tests/e2e/mqttct/dependencies.bicep @@ -25,7 +25,10 @@ resource eventGridTopicRbacAssignment 'Microsoft.Authorization/roleAssignments@2 name: guid(managedIdentity.id, 'evgtRbacAssignment') scope: eventGridTopic properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7') // EventGrid Data Sender + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'd5a91429-5739-47e2-a06b-3470a27159e7' + ) // EventGrid Data Sender principalId: managedIdentity.properties.principalId principalType: 'ServicePrincipal' } diff --git a/avm/res/event-grid/namespace/tests/e2e/mqttct/main.test.bicep b/avm/res/event-grid/namespace/tests/e2e/mqttct/main.test.bicep index 382a608544..79830836b6 100644 --- a/avm/res/event-grid/namespace/tests/e2e/mqttct/main.test.bicep +++ b/avm/res/event-grid/namespace/tests/e2e/mqttct/main.test.bicep @@ -46,149 +46,154 @@ 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 - managedIdentities: { - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - topics: [ - { - name: 'topic1' +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: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] } - ] - topicSpacesState: 'Enabled' - maximumClientSessionsPerAuthenticationName: 5 - maximumSessionExpiryInHours: 2 - routeTopicResourceId: nestedDependencies.outputs.eventGridTopicResourceId - routingIdentityInfo: { - type: 'UserAssigned' - userAssignedIdentity: nestedDependencies.outputs.managedIdentityResourceId - } - routingEnrichments: { - static: [ + topics: [ { - key: 'static1' - value: 'value1' - valueType: 'String' - } - { - key: 'static2' - value: 'value2' - valueType: 'String' - } - ] - dynamic: [ - { - key: 'dynamic1' - value: '\${client.authenticationName}' + name: 'topic1' } ] - } - alternativeAuthenticationNameSources: [ - 'ClientCertificateEmail' - 'ClientCertificateUri' - ] - // caCertificates: [ - // { - // name: 'exampleCert' - // encodedCertificate: ''' - // ''' - // } - // ] - clients: [ - { - name: 'client1' - authenticationName: 'client2auth' - description: 'this is client2' - clientCertificateAuthenticationValidationSchema: 'ThumbprintMatch' - clientCertificateAuthenticationAllowedThumbprints: [ - '1111111111111111111111111111111111111111' - '2222222222222222222222222222222222222222' - ] - state: 'Enabled' - attributes: { - room: '345' - floor: 12 - deviceTypes: [ - 'Fan' - 'Light' - ] - } - } - { - name: 'client2' - clientCertificateAuthenticationValidationSchema: 'ThumbprintMatch' - clientCertificateAuthenticationAllowedThumbprints: [ - '3333333333333333333333333333333333333333' - ] - } - { - name: 'client3' - } - { - name: 'client4' - clientCertificateAuthenticationValidationSchema: 'IpMatchesAuthenticationName' - } - ] - clientGroups: [ - { - name: 'group1' - query: 'attributes.keyName IN [\'a\', \'b\', \'c\']' - description: 'this is group1' - } - ] - topicSpaces: [ - { - name: 'topicSpace1' - topicTemplates: [ - 'devices/foo/bar' - 'devices/topic1/+' - ] + topicSpacesState: 'Enabled' + maximumClientSessionsPerAuthenticationName: 5 + maximumSessionExpiryInHours: 2 + routeTopicResourceId: nestedDependencies.outputs.eventGridTopicResourceId + routingIdentityInfo: { + type: 'UserAssigned' + userAssignedIdentity: nestedDependencies.outputs.managedIdentityResourceId } - { - name: 'topicSpace2' - topicTemplates: [ - 'devices/topic1/+' - ] - roleAssignments: [ + routingEnrichments: { + static: [ { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + key: 'static1' + value: 'value1' + valueType: 'String' } { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + key: 'static2' + value: 'value2' + valueType: 'String' } + ] + dynamic: [ { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + key: 'dynamic1' + value: '\${client.authenticationName}' } ] } - ] - permissionBindings: [ - { - name: 'bindiing1' - description: 'this is binding1' - clientGroupName: 'group1' - topicSpaceName: 'topicSpace1' - permission: 'Publisher' - } - { - name: 'bindiing2' - clientGroupName: 'group1' - topicSpaceName: 'topicSpace2' - permission: 'Subscriber' - } - ] + alternativeAuthenticationNameSources: [ + 'ClientCertificateEmail' + 'ClientCertificateUri' + ] + // caCertificates: [ + // { + // name: 'exampleCert' + // encodedCertificate: ''' + // ''' + // } + // ] + clients: [ + { + name: 'client1' + authenticationName: 'client2auth' + description: 'this is client2' + clientCertificateAuthenticationValidationSchema: 'ThumbprintMatch' + clientCertificateAuthenticationAllowedThumbprints: [ + '1111111111111111111111111111111111111111' + '2222222222222222222222222222222222222222' + ] + state: 'Enabled' + attributes: { + room: '345' + floor: 12 + deviceTypes: [ + 'Fan' + 'Light' + ] + } + } + { + name: 'client2' + clientCertificateAuthenticationValidationSchema: 'ThumbprintMatch' + clientCertificateAuthenticationAllowedThumbprints: [ + '3333333333333333333333333333333333333333' + ] + } + { + name: 'client3' + } + { + name: 'client4' + clientCertificateAuthenticationValidationSchema: 'IpMatchesAuthenticationName' + } + ] + clientGroups: [ + { + name: 'group1' + query: 'attributes.keyName IN [\'a\', \'b\', \'c\']' + description: 'this is group1' + } + ] + topicSpaces: [ + { + name: 'topicSpace1' + topicTemplates: [ + 'devices/foo/bar' + 'devices/topic1/+' + ] + } + { + name: 'topicSpace2' + topicTemplates: [ + 'devices/topic1/+' + ] + 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' + } + ] + } + ] + permissionBindings: [ + { + name: 'bindiing1' + description: 'this is binding1' + clientGroupName: 'group1' + topicSpaceName: 'topicSpace1' + permission: 'Publisher' + } + { + name: 'bindiing2' + clientGroupName: 'group1' + topicSpaceName: 'topicSpace2' + permission: 'Subscriber' + } + ] + } } -}] +] 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 40265c3ba5..e2a8332ca0 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 @@ -47,149 +47,154 @@ 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 - managedIdentities: { - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - topics: [ - { - name: 'topic1' +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: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] } - ] - topicSpacesState: 'Enabled' - maximumClientSessionsPerAuthenticationName: 5 - maximumSessionExpiryInHours: 2 - routeTopicResourceId: nestedDependencies.outputs.eventGridNameSpaceTopicResourceId - routingIdentityInfo: { - type: 'UserAssigned' - userAssignedIdentity: nestedDependencies.outputs.managedIdentityResourceId - } - routingEnrichments: { - static: [ + topics: [ { - key: 'static1' - value: 'value1' - valueType: 'String' - } - { - key: 'static2' - value: 'value2' - valueType: 'String' - } - ] - dynamic: [ - { - key: 'dynamic1' - value: '\${client.authenticationName}' + name: 'topic1' } ] - } - alternativeAuthenticationNameSources: [ - 'ClientCertificateEmail' - 'ClientCertificateUri' - ] - // caCertificates: [ - // { - // name: 'exampleCert' - // encodedCertificate: ''' - // ''' - // } - // ] - clients: [ - { - name: 'client1' - authenticationName: 'client2auth' - description: 'this is client2' - clientCertificateAuthenticationValidationSchema: 'ThumbprintMatch' - clientCertificateAuthenticationAllowedThumbprints: [ - '1111111111111111111111111111111111111111' - '2222222222222222222222222222222222222222' - ] - state: 'Enabled' - attributes: { - room: '345' - floor: 12 - deviceTypes: [ - 'Fan' - 'Light' - ] - } - } - { - name: 'client2' - clientCertificateAuthenticationValidationSchema: 'ThumbprintMatch' - clientCertificateAuthenticationAllowedThumbprints: [ - '3333333333333333333333333333333333333333' - ] - } - { - name: 'client3' - } - { - name: 'client4' - clientCertificateAuthenticationValidationSchema: 'IpMatchesAuthenticationName' - } - ] - clientGroups: [ - { - name: 'group1' - query: 'attributes.keyName IN [\'a\', \'b\', \'c\']' - description: 'this is group1' - } - ] - topicSpaces: [ - { - name: 'topicSpace1' - topicTemplates: [ - 'devices/foo/bar' - 'devices/topic1/+' - ] + topicSpacesState: 'Enabled' + maximumClientSessionsPerAuthenticationName: 5 + maximumSessionExpiryInHours: 2 + routeTopicResourceId: nestedDependencies.outputs.eventGridNameSpaceTopicResourceId + routingIdentityInfo: { + type: 'UserAssigned' + userAssignedIdentity: nestedDependencies.outputs.managedIdentityResourceId } - { - name: 'topicSpace2' - topicTemplates: [ - 'devices/topic1/+' - ] - roleAssignments: [ + routingEnrichments: { + static: [ { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + key: 'static1' + value: 'value1' + valueType: 'String' } { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + key: 'static2' + value: 'value2' + valueType: 'String' } + ] + dynamic: [ { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + key: 'dynamic1' + value: '\${client.authenticationName}' } ] } - ] - permissionBindings: [ - { - name: 'bindiing1' - description: 'this is binding1' - clientGroupName: 'group1' - topicSpaceName: 'topicSpace1' - permission: 'Publisher' - } - { - name: 'bindiing2' - clientGroupName: 'group1' - topicSpaceName: 'topicSpace2' - permission: 'Subscriber' - } - ] + alternativeAuthenticationNameSources: [ + 'ClientCertificateEmail' + 'ClientCertificateUri' + ] + // caCertificates: [ + // { + // name: 'exampleCert' + // encodedCertificate: ''' + // ''' + // } + // ] + clients: [ + { + name: 'client1' + authenticationName: 'client2auth' + description: 'this is client2' + clientCertificateAuthenticationValidationSchema: 'ThumbprintMatch' + clientCertificateAuthenticationAllowedThumbprints: [ + '1111111111111111111111111111111111111111' + '2222222222222222222222222222222222222222' + ] + state: 'Enabled' + attributes: { + room: '345' + floor: 12 + deviceTypes: [ + 'Fan' + 'Light' + ] + } + } + { + name: 'client2' + clientCertificateAuthenticationValidationSchema: 'ThumbprintMatch' + clientCertificateAuthenticationAllowedThumbprints: [ + '3333333333333333333333333333333333333333' + ] + } + { + name: 'client3' + } + { + name: 'client4' + clientCertificateAuthenticationValidationSchema: 'IpMatchesAuthenticationName' + } + ] + clientGroups: [ + { + name: 'group1' + query: 'attributes.keyName IN [\'a\', \'b\', \'c\']' + description: 'this is group1' + } + ] + topicSpaces: [ + { + name: 'topicSpace1' + topicTemplates: [ + 'devices/foo/bar' + 'devices/topic1/+' + ] + } + { + name: 'topicSpace2' + topicTemplates: [ + 'devices/topic1/+' + ] + 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' + } + ] + } + ] + permissionBindings: [ + { + name: 'bindiing1' + description: 'this is binding1' + clientGroupName: 'group1' + topicSpaceName: 'topicSpace1' + permission: 'Publisher' + } + { + name: 'bindiing2' + clientGroupName: 'group1' + topicSpaceName: 'topicSpace2' + permission: 'Subscriber' + } + ] + } } -}] +] diff --git a/avm/res/event-grid/namespace/tests/e2e/waf-aligned/main.test.bicep b/avm/res/event-grid/namespace/tests/e2e/waf-aligned/main.test.bicep index 62eef80089..a7f5df77a0 100644 --- a/avm/res/event-grid/namespace/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/event-grid/namespace/tests/e2e/waf-aligned/main.test.bicep @@ -60,60 +60,65 @@ 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 - diagnosticSettings: [ - { - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - privateEndpoints: [ - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +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 + diagnosticSettings: [ + { + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } + ] + privateEndpoints: [ + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + } + ] + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - } - ] - 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' - } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/event-grid/namespace/topic-space/main.bicep b/avm/res/event-grid/namespace/topic-space/main.bicep index f3e9e4e149..23cec86c04 100644 --- a/avm/res/event-grid/namespace/topic-space/main.bicep +++ b/avm/res/event-grid/namespace/topic-space/main.bicep @@ -19,19 +19,49 @@ param topicTemplates array param roleAssignments roleAssignmentType var builtInRoleNames = { - 'Azure Resource Notifications System Topics Subscriber': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0b962ed2-6d56-471c-bd5f-3477d83a7ba4') + 'Azure Resource Notifications System Topics Subscriber': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '0b962ed2-6d56-471c-bd5f-3477d83a7ba4' + ) Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'EventGrid Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1e241071-0855-49ea-94dc-649edcd759de') - 'EventGrid Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d8c3fe3-8864-474b-8749-01e3783e8157') - 'EventGrid Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '78cbd9e7-9798-4e2e-9b5a-547d9ebb31fb') - 'EventGrid Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7') - 'EventGrid EventSubscription Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443') - 'EventGrid EventSubscription Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405') - 'EventGrid TopicSpaces Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a12b0b94-b317-4dcd-84a8-502ce99884c6') - 'EventGrid TopicSpaces Subscriber': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4b0f2fd7-60b4-4eca-896f-4435034f8bf5') + 'EventGrid Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '1e241071-0855-49ea-94dc-649edcd759de' + ) + 'EventGrid Data Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '1d8c3fe3-8864-474b-8749-01e3783e8157' + ) + 'EventGrid Data Receiver': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '78cbd9e7-9798-4e2e-9b5a-547d9ebb31fb' + ) + 'EventGrid Data Sender': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'd5a91429-5739-47e2-a06b-3470a27159e7' + ) + 'EventGrid EventSubscription Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '428e0ff0-5e57-4d9c-a221-2c70d0e0a443' + ) + 'EventGrid EventSubscription Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '2414bbcf-6497-4faf-8c65-045460748405' + ) + 'EventGrid TopicSpaces Publisher': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'a12b0b94-b317-4dcd-84a8-502ce99884c6' + ) + 'EventGrid TopicSpaces Subscriber': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '4b0f2fd7-60b4-4eca-896f-4435034f8bf5' + ) Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'User Access Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + ) } // ============== // @@ -51,19 +81,25 @@ resource topicSpace 'Microsoft.EventGrid/namespaces/topicSpaces@2023-12-15-previ } } -resource topic_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(topicSpace.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource topic_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(topicSpace.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: topicSpace } - scope: topicSpace -}] +] // ============ // // Outputs // diff --git a/avm/res/event-grid/namespace/topic-space/main.json b/avm/res/event-grid/namespace/topic-space/main.json index f094351427..c0b7cff6d7 100644 --- a/avm/res/event-grid/namespace/topic-space/main.json +++ b/avm/res/event-grid/namespace/topic-space/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "6548696237893842735" + "version": "0.26.54.24096", + "templateHash": "4931718668767892926" }, "name": "Eventgrid Namespace Topic Spaces", "description": "This module deploys an Eventgrid Namespace Topic Space.", diff --git a/avm/res/event-grid/namespace/topic/event-subscription/main.bicep b/avm/res/event-grid/namespace/topic/event-subscription/main.bicep index f8d8c63bfc..553032cc47 100644 --- a/avm/res/event-grid/namespace/topic/event-subscription/main.bicep +++ b/avm/res/event-grid/namespace/topic/event-subscription/main.bicep @@ -24,19 +24,49 @@ param filtersConfiguration object? param roleAssignments roleAssignmentType var builtInRoleNames = { - 'Azure Resource Notifications System Topics Subscriber': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0b962ed2-6d56-471c-bd5f-3477d83a7ba4') + 'Azure Resource Notifications System Topics Subscriber': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '0b962ed2-6d56-471c-bd5f-3477d83a7ba4' + ) Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'EventGrid Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1e241071-0855-49ea-94dc-649edcd759de') - 'EventGrid Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d8c3fe3-8864-474b-8749-01e3783e8157') - 'EventGrid Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '78cbd9e7-9798-4e2e-9b5a-547d9ebb31fb') - 'EventGrid Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7') - 'EventGrid EventSubscription Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443') - 'EventGrid EventSubscription Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405') - 'EventGrid TopicSpaces Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a12b0b94-b317-4dcd-84a8-502ce99884c6') - 'EventGrid TopicSpaces Subscriber': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4b0f2fd7-60b4-4eca-896f-4435034f8bf5') + 'EventGrid Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '1e241071-0855-49ea-94dc-649edcd759de' + ) + 'EventGrid Data Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '1d8c3fe3-8864-474b-8749-01e3783e8157' + ) + 'EventGrid Data Receiver': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '78cbd9e7-9798-4e2e-9b5a-547d9ebb31fb' + ) + 'EventGrid Data Sender': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'd5a91429-5739-47e2-a06b-3470a27159e7' + ) + 'EventGrid EventSubscription Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '428e0ff0-5e57-4d9c-a221-2c70d0e0a443' + ) + 'EventGrid EventSubscription Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '2414bbcf-6497-4faf-8c65-045460748405' + ) + 'EventGrid TopicSpaces Publisher': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'a12b0b94-b317-4dcd-84a8-502ce99884c6' + ) + 'EventGrid TopicSpaces Subscriber': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '4b0f2fd7-60b4-4eca-896f-4435034f8bf5' + ) Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'User Access Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + ) } // ============== // @@ -61,19 +91,25 @@ resource eventSubscription 'Microsoft.EventGrid/namespaces/topics/eventSubscript } } -resource eventSubscription_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(eventSubscription.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource eventSubscription_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(eventSubscription.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: eventSubscription } - scope: eventSubscription -}] +] // ============ // // Outputs // diff --git a/avm/res/event-grid/namespace/topic/event-subscription/main.json b/avm/res/event-grid/namespace/topic/event-subscription/main.json index 6895d512f1..e2c0296a00 100644 --- a/avm/res/event-grid/namespace/topic/event-subscription/main.json +++ b/avm/res/event-grid/namespace/topic/event-subscription/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "13130499975324434363" + "version": "0.26.54.24096", + "templateHash": "18248314164362964337" }, "name": "Event Subscriptions", "description": "This module deploys an Event Subscription.", diff --git a/avm/res/event-grid/namespace/topic/main.bicep b/avm/res/event-grid/namespace/topic/main.bicep index 9bc8a5fe64..6f9e29f534 100644 --- a/avm/res/event-grid/namespace/topic/main.bicep +++ b/avm/res/event-grid/namespace/topic/main.bicep @@ -29,19 +29,49 @@ param publisherType string = 'Custom' param eventSubscriptions array? var builtInRoleNames = { - 'Azure Resource Notifications System Topics Subscriber': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0b962ed2-6d56-471c-bd5f-3477d83a7ba4') + 'Azure Resource Notifications System Topics Subscriber': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '0b962ed2-6d56-471c-bd5f-3477d83a7ba4' + ) Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'EventGrid Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1e241071-0855-49ea-94dc-649edcd759de') - 'EventGrid Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d8c3fe3-8864-474b-8749-01e3783e8157') - 'EventGrid Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '78cbd9e7-9798-4e2e-9b5a-547d9ebb31fb') - 'EventGrid Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7') - 'EventGrid EventSubscription Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443') - 'EventGrid EventSubscription Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405') - 'EventGrid TopicSpaces Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a12b0b94-b317-4dcd-84a8-502ce99884c6') - 'EventGrid TopicSpaces Subscriber': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4b0f2fd7-60b4-4eca-896f-4435034f8bf5') + 'EventGrid Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '1e241071-0855-49ea-94dc-649edcd759de' + ) + 'EventGrid Data Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '1d8c3fe3-8864-474b-8749-01e3783e8157' + ) + 'EventGrid Data Receiver': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '78cbd9e7-9798-4e2e-9b5a-547d9ebb31fb' + ) + 'EventGrid Data Sender': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'd5a91429-5739-47e2-a06b-3470a27159e7' + ) + 'EventGrid EventSubscription Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '428e0ff0-5e57-4d9c-a221-2c70d0e0a443' + ) + 'EventGrid EventSubscription Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '2414bbcf-6497-4faf-8c65-045460748405' + ) + 'EventGrid TopicSpaces Publisher': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'a12b0b94-b317-4dcd-84a8-502ce99884c6' + ) + 'EventGrid TopicSpaces Subscriber': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '4b0f2fd7-60b4-4eca-896f-4435034f8bf5' + ) Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'User Access Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + ) } // ============== // @@ -62,41 +92,52 @@ resource topic 'Microsoft.EventGrid/namespaces/topics@2023-12-15-preview' = { } } -resource topic_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.' +resource topic_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: topic } - scope: topic -} -resource topic_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(topic.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource topic_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(topic.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: topic } - scope: topic -}] - -module topic_eventSubscriptions 'event-subscription/main.bicep' = [for (eventSubscription, index) in (eventSubscriptions ?? []): { - name: '${uniqueString(deployment().name, topic.name)}-Topic-EventSubscription-${index}' - params: { - name: eventSubscription.name - namespaceName: namespace.name - topicName: topic.name - deliveryConfiguration: eventSubscription.?deliveryConfiguration - eventDeliverySchema: eventSubscription.?eventDeliverySchema - filtersConfiguration: eventSubscription.?filtersConfiguration - roleAssignments: eventSubscription.?roleAssignments +] + +module topic_eventSubscriptions 'event-subscription/main.bicep' = [ + for (eventSubscription, index) in (eventSubscriptions ?? []): { + name: '${uniqueString(deployment().name, topic.name)}-Topic-EventSubscription-${index}' + params: { + name: eventSubscription.name + namespaceName: namespace.name + topicName: topic.name + deliveryConfiguration: eventSubscription.?deliveryConfiguration + eventDeliverySchema: eventSubscription.?eventDeliverySchema + filtersConfiguration: eventSubscription.?filtersConfiguration + roleAssignments: eventSubscription.?roleAssignments + } } -}] +] // ============ // // Outputs // diff --git a/avm/res/event-grid/namespace/topic/main.json b/avm/res/event-grid/namespace/topic/main.json index 60a89a526b..0249d1ea0e 100644 --- a/avm/res/event-grid/namespace/topic/main.json +++ b/avm/res/event-grid/namespace/topic/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2836208779363789051" + "version": "0.26.54.24096", + "templateHash": "4459336414537252998" }, "name": "Eventgrid Namespace Topics", "description": "This module deploys an Eventgrid Namespace Topic.", @@ -277,8 +277,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "13130499975324434363" + "version": "0.26.54.24096", + "templateHash": "18248314164362964337" }, "name": "Event Subscriptions", "description": "This module deploys an Event Subscription.", diff --git a/avm/res/event-grid/system-topic/event-subscription/main.bicep b/avm/res/event-grid/system-topic/event-subscription/main.bicep index c4390be179..0dde5e9ed3 100644 --- a/avm/res/event-grid/system-topic/event-subscription/main.bicep +++ b/avm/res/event-grid/system-topic/event-subscription/main.bicep @@ -21,14 +21,12 @@ param deliveryWithResourceIdentity object = {} param destination object @description('Optional. The event delivery schema for the event subscription.') -@allowed( - [ - 'CloudEventSchemaV1_0' - 'CustomInputSchema' - 'EventGridSchema' - 'EventGridEvent' - ] -) +@allowed([ + 'CloudEventSchemaV1_0' + 'CustomInputSchema' + 'EventGridSchema' + 'EventGridEvent' +]) param eventDeliverySchema string = 'EventGridSchema' @description('Optional. The expiration time for the event subscription. Format is ISO-8601 (yyyy-MM-ddTHH:mm:ssZ).') diff --git a/avm/res/event-grid/system-topic/event-subscription/main.json b/avm/res/event-grid/system-topic/event-subscription/main.json index bd8f0faa07..16c30b2cc1 100644 --- a/avm/res/event-grid/system-topic/event-subscription/main.json +++ b/avm/res/event-grid/system-topic/event-subscription/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "5245070501778317327" + "version": "0.26.54.24096", + "templateHash": "10785513325752294615" }, "name": "Event Grid System Topic Event Subscriptions", "description": "This module deploys an Event Grid System Topic Event Subscription.", diff --git a/avm/res/event-grid/system-topic/main.bicep b/avm/res/event-grid/system-topic/main.bicep index 4224e2fb28..8595d6fa1d 100644 --- a/avm/res/event-grid/system-topic/main.bicep +++ b/avm/res/event-grid/system-topic/main.bicep @@ -35,42 +35,72 @@ param tags object? @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -var formattedUserAssignedIdentities = reduce(map((managedIdentities.?userAssignedResourcesIds ?? []), (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.?userAssignedResourcesIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(managedIdentities.?userAssignedResourcesIds ?? {}) ? 'UserAssigned' : null) - userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null -} : null +var formattedUserAssignedIdentities = reduce( + map((managedIdentities.?userAssignedResourcesIds ?? []), (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.?userAssignedResourcesIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') + : (!empty(managedIdentities.?userAssignedResourcesIds ?? {}) ? 'UserAssigned' : null) + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null + } + : null var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'EventGrid Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1e241071-0855-49ea-94dc-649edcd759de') - 'EventGrid Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7') - 'EventGrid EventSubscription Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443') - 'EventGrid EventSubscription Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405') + 'EventGrid Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '1e241071-0855-49ea-94dc-649edcd759de' + ) + 'EventGrid Data Sender': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'd5a91429-5739-47e2-a06b-3470a27159e7' + ) + 'EventGrid EventSubscription Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '428e0ff0-5e57-4d9c-a221-2c70d0e0a443' + ) + 'EventGrid EventSubscription Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '2414bbcf-6497-4faf-8c65-045460748405' + ) 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') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: take('46d3xbcp.res.eventgrid-systemtopic.${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' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: take( + '46d3xbcp.res.eventgrid-systemtopic.${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' + } } } } } -} resource systemTopic 'Microsoft.EventGrid/systemTopics@2021-12-01' = { name: name @@ -84,68 +114,93 @@ resource systemTopic 'Microsoft.EventGrid/systemTopics@2021-12-01' = { } // Event subscriptions -module systemTopics_eventSubscriptions 'event-subscription/main.bicep' = [for (eventSubscription, index) in eventSubscriptions: { - name: '${uniqueString(deployment().name, location)}-EventGrid-SystemTopics-EventSubscriptions-${index}' - params: { - destination: eventSubscription.destination - systemTopicName: systemTopic.name - name: eventSubscription.name - deadLetterDestination: contains(eventSubscription, 'deadLetterDestination') ? eventSubscription.deadLetterDestination : {} - deadLetterWithResourceIdentity: contains(eventSubscription, 'deadLetterWithResourceIdentity') ? eventSubscription.deadLetterWithResourceIdentity : {} - deliveryWithResourceIdentity: contains(eventSubscription, 'deliveryWithResourceIdentity') ? eventSubscription.deliveryWithResourceIdentity : {} - eventDeliverySchema: contains(eventSubscription, 'eventDeliverySchema') ? eventSubscription.eventDeliverySchema : 'EventGridSchema' - expirationTimeUtc: contains(eventSubscription, 'expirationTimeUtc') ? eventSubscription.expirationTimeUtc : '' - filter: contains(eventSubscription, 'filter') ? eventSubscription.filter : {} - labels: contains(eventSubscription, 'labels') ? eventSubscription.labels : [] - retryPolicy: contains(eventSubscription, 'retryPolicy') ? eventSubscription.retryPolicy : {} +module systemTopics_eventSubscriptions 'event-subscription/main.bicep' = [ + for (eventSubscription, index) in eventSubscriptions: { + name: '${uniqueString(deployment().name, location)}-EventGrid-SystemTopics-EventSubscriptions-${index}' + params: { + destination: eventSubscription.destination + systemTopicName: systemTopic.name + name: eventSubscription.name + deadLetterDestination: contains(eventSubscription, 'deadLetterDestination') + ? eventSubscription.deadLetterDestination + : {} + deadLetterWithResourceIdentity: contains(eventSubscription, 'deadLetterWithResourceIdentity') + ? eventSubscription.deadLetterWithResourceIdentity + : {} + deliveryWithResourceIdentity: contains(eventSubscription, 'deliveryWithResourceIdentity') + ? eventSubscription.deliveryWithResourceIdentity + : {} + eventDeliverySchema: contains(eventSubscription, 'eventDeliverySchema') + ? eventSubscription.eventDeliverySchema + : 'EventGridSchema' + expirationTimeUtc: contains(eventSubscription, 'expirationTimeUtc') ? eventSubscription.expirationTimeUtc : '' + filter: contains(eventSubscription, 'filter') ? eventSubscription.filter : {} + labels: contains(eventSubscription, 'labels') ? eventSubscription.labels : [] + retryPolicy: contains(eventSubscription, 'retryPolicy') ? eventSubscription.retryPolicy : {} + } } -}] - -resource systemTopic_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.' +] + +resource systemTopic_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: systemTopic } - scope: systemTopic -} -resource systemTopic_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource systemTopic_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: systemTopic } - scope: systemTopic -}] - -resource systemTopic_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(systemTopic.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +] + +resource systemTopic_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(systemTopic.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: systemTopic } - scope: systemTopic -}] +] @description('The name of the event grid system topic.') output name string = systemTopic.name diff --git a/avm/res/event-grid/system-topic/main.json b/avm/res/event-grid/system-topic/main.json index 2844dda4b8..67bfb016c7 100644 --- a/avm/res/event-grid/system-topic/main.json +++ b/avm/res/event-grid/system-topic/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "8773071401179464366" + "version": "0.26.54.24096", + "templateHash": "6398074442417781494" }, "name": "Event Grid System Topics", "description": "This module deploys an Event Grid System Topic.", @@ -483,8 +483,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "5245070501778317327" + "version": "0.26.54.24096", + "templateHash": "10785513325752294615" }, "name": "Event Grid System Topic Event Subscriptions", "description": "This module deploys an Event Grid System Topic Event Subscription.", diff --git a/avm/res/event-grid/system-topic/tests/e2e/defaults/dependencies.bicep b/avm/res/event-grid/system-topic/tests/e2e/defaults/dependencies.bicep index 61ebc54d90..04ef3b2647 100644 --- a/avm/res/event-grid/system-topic/tests/e2e/defaults/dependencies.bicep +++ b/avm/res/event-grid/system-topic/tests/e2e/defaults/dependencies.bicep @@ -5,12 +5,12 @@ param location string = resourceGroup().location param storageAccountName string resource storageAccount 'Microsoft.Storage/storageAccounts@2022-05-01' = { - name: storageAccountName - location: location - sku: { - name: 'Standard_LRS' - } - kind: 'StorageV2' + name: storageAccountName + location: location + sku: { + name: 'Standard_LRS' + } + kind: 'StorageV2' } @description('The resource ID of the created Storage Account.') diff --git a/avm/res/event-grid/system-topic/tests/e2e/defaults/main.test.bicep b/avm/res/event-grid/system-topic/tests/e2e/defaults/main.test.bicep index a5121372c9..122e408292 100644 --- a/avm/res/event-grid/system-topic/tests/e2e/defaults/main.test.bicep +++ b/avm/res/event-grid/system-topic/tests/e2e/defaults/main.test.bicep @@ -59,13 +59,15 @@ 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' - source: nestedDependencies.outputs.storageAccountResourceId - topicType: 'Microsoft.Storage.StorageAccounts' - location: resourceLocation +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + source: nestedDependencies.outputs.storageAccountResourceId + topicType: 'Microsoft.Storage.StorageAccounts' + location: resourceLocation + } } -}] +] diff --git a/avm/res/event-grid/system-topic/tests/e2e/max/dependencies.bicep b/avm/res/event-grid/system-topic/tests/e2e/max/dependencies.bicep index 9b192272d4..ddb6369cc0 100644 --- a/avm/res/event-grid/system-topic/tests/e2e/max/dependencies.bicep +++ b/avm/res/event-grid/system-topic/tests/e2e/max/dependencies.bicep @@ -11,25 +11,25 @@ param storageAccountName string param storageQueueName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } resource storageAccount 'Microsoft.Storage/storageAccounts@2022-05-01' = { - name: storageAccountName - location: location - sku: { - name: 'Standard_LRS' - } - kind: 'StorageV2' - - resource queueService 'queueServices@2022-09-01' = { - name: 'default' - - resource queue 'queues@2022-09-01' = { - name: storageQueueName - } + name: storageAccountName + location: location + sku: { + name: 'Standard_LRS' + } + kind: 'StorageV2' + + resource queueService 'queueServices@2022-09-01' = { + name: 'default' + + resource queue 'queues@2022-09-01' = { + name: storageQueueName } + } } @description('The name of the created Storage Account Queue.') diff --git a/avm/res/event-grid/system-topic/tests/e2e/max/main.test.bicep b/avm/res/event-grid/system-topic/tests/e2e/max/main.test.bicep index fc6bf1aef4..c239434df1 100644 --- a/avm/res/event-grid/system-topic/tests/e2e/max/main.test.bicep +++ b/avm/res/event-grid/system-topic/tests/e2e/max/main.test.bicep @@ -60,77 +60,84 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t // 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' - source: nestedDependencies.outputs.storageAccountResourceId - topicType: 'Microsoft.Storage.StorageAccounts' - location: resourceLocation - eventSubscriptions: [ { - name: '${namePrefix}${serviceShort}001' - expirationTimeUtc: '2099-01-01T11:00:21.715Z' - filter: { - isSubjectCaseSensitive: false - enableAdvancedFilteringOnArrays: true - } - retryPolicy: { - maxDeliveryAttempts: 10 - eventTimeToLive: '120' - } - eventDeliverySchema: 'CloudEventSchemaV1_0' - destination: { - endpointType: 'StorageQueue' - properties: { - resourceId: nestedDependencies.outputs.storageAccountResourceId - queueMessageTimeToLiveInSeconds: 86400 - queueName: nestedDependencies.outputs.queueName +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + source: nestedDependencies.outputs.storageAccountResourceId + topicType: 'Microsoft.Storage.StorageAccounts' + location: resourceLocation + eventSubscriptions: [ + { + name: '${namePrefix}${serviceShort}001' + expirationTimeUtc: '2099-01-01T11:00:21.715Z' + filter: { + isSubjectCaseSensitive: false + enableAdvancedFilteringOnArrays: true } - } - } ] - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' + retryPolicy: { + maxDeliveryAttempts: 10 + eventTimeToLive: '120' } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - managedIdentities: { - systemAssigned: true - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + eventDeliverySchema: 'CloudEventSchemaV1_0' + destination: { + endpointType: 'StorageQueue' + properties: { + resourceId: nestedDependencies.outputs.storageAccountResourceId + queueMessageTimeToLiveInSeconds: 86400 + queueName: nestedDependencies.outputs.queueName + } + } + } + ] + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + managedIdentities: { + systemAssigned: true } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/event-grid/system-topic/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/event-grid/system-topic/tests/e2e/waf-aligned/dependencies.bicep index d53fdbeaa6..8de4272d56 100644 --- a/avm/res/event-grid/system-topic/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/event-grid/system-topic/tests/e2e/waf-aligned/dependencies.bicep @@ -8,20 +8,20 @@ param storageAccountName string param storageQueueName string resource storageAccount 'Microsoft.Storage/storageAccounts@2022-05-01' = { - name: storageAccountName - location: location - sku: { - name: 'Standard_LRS' - } - kind: 'StorageV2' + name: storageAccountName + location: location + sku: { + name: 'Standard_LRS' + } + kind: 'StorageV2' - resource queueService 'queueServices@2022-09-01' = { - name: 'default' + resource queueService 'queueServices@2022-09-01' = { + name: 'default' - resource queue 'queues@2022-09-01' = { - name: storageQueueName - } + resource queue 'queues@2022-09-01' = { + name: storageQueueName } + } } @description('The name of the created Storage Account Queue.') diff --git a/avm/res/event-grid/system-topic/tests/e2e/waf-aligned/main.test.bicep b/avm/res/event-grid/system-topic/tests/e2e/waf-aligned/main.test.bicep index 1fd7a058c0..27154e7191 100644 --- a/avm/res/event-grid/system-topic/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/event-grid/system-topic/tests/e2e/waf-aligned/main.test.bicep @@ -60,57 +60,61 @@ 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' - source: nestedDependencies.outputs.storageAccountResourceId - topicType: 'Microsoft.Storage.StorageAccounts' - location: resourceLocation - eventSubscriptions: [ { - name: '${namePrefix}${serviceShort}001' - expirationTimeUtc: '2099-01-01T11:00:21.715Z' - filter: { - isSubjectCaseSensitive: false - enableAdvancedFilteringOnArrays: true - } - retryPolicy: { - maxDeliveryAttempts: 10 - eventTimeToLive: '120' - } - eventDeliverySchema: 'CloudEventSchemaV1_0' - destination: { - endpointType: 'StorageQueue' - properties: { - resourceId: nestedDependencies.outputs.storageAccountResourceId - queueMessageTimeToLiveInSeconds: 86400 - queueName: nestedDependencies.outputs.queueName +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + source: nestedDependencies.outputs.storageAccountResourceId + topicType: 'Microsoft.Storage.StorageAccounts' + location: resourceLocation + eventSubscriptions: [ + { + name: '${namePrefix}${serviceShort}001' + expirationTimeUtc: '2099-01-01T11:00:21.715Z' + filter: { + isSubjectCaseSensitive: false + enableAdvancedFilteringOnArrays: true } - } - } ] - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' + retryPolicy: { + maxDeliveryAttempts: 10 + eventTimeToLive: '120' } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + eventDeliverySchema: 'CloudEventSchemaV1_0' + destination: { + endpointType: 'StorageQueue' + properties: { + resourceId: nestedDependencies.outputs.storageAccountResourceId + queueMessageTimeToLiveInSeconds: 86400 + queueName: nestedDependencies.outputs.queueName + } + } + } + ] + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/event-grid/topic/event-subscription/main.bicep b/avm/res/event-grid/topic/event-subscription/main.bicep index 478e271988..2fa42cb4fa 100644 --- a/avm/res/event-grid/topic/event-subscription/main.bicep +++ b/avm/res/event-grid/topic/event-subscription/main.bicep @@ -21,14 +21,12 @@ param deliveryWithResourceIdentity object = {} param destination object @description('Optional. The event delivery schema for the event subscription.') -@allowed( - [ - 'CloudEventSchemaV1_0' - 'CustomInputSchema' - 'EventGridSchema' - 'EventGridEvent' - ] -) +@allowed([ + 'CloudEventSchemaV1_0' + 'CustomInputSchema' + 'EventGridSchema' + 'EventGridEvent' +]) param eventDeliverySchema string = 'EventGridSchema' @description('Optional. The expiration time for the event subscription. Format is ISO-8601 (yyyy-MM-ddTHH:mm:ssZ).') @@ -54,7 +52,7 @@ resource eventSubscription 'Microsoft.EventGrid/topics/eventSubscriptions@2022-0 deadLetterDestination: !empty(deadLetterDestination) ? deadLetterDestination : null deadLetterWithResourceIdentity: !empty(deadLetterWithResourceIdentity) ? deadLetterWithResourceIdentity : null deliveryWithResourceIdentity: !empty(deliveryWithResourceIdentity) ? deliveryWithResourceIdentity : null - destination: empty(deliveryWithResourceIdentity) ? destination: null + destination: empty(deliveryWithResourceIdentity) ? destination : null eventDeliverySchema: eventDeliverySchema expirationTimeUtc: !empty(expirationTimeUtc) ? expirationTimeUtc : '' filter: !empty(filter) ? filter : {} diff --git a/avm/res/event-grid/topic/event-subscription/main.json b/avm/res/event-grid/topic/event-subscription/main.json index c73adf1ab6..4ffd84afa9 100644 --- a/avm/res/event-grid/topic/event-subscription/main.json +++ b/avm/res/event-grid/topic/event-subscription/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "12495597102731978024" + "version": "0.26.54.24096", + "templateHash": "12645668843865460856" }, "name": "EventGrid Topic Event Subscriptions", "description": "This module deploys an Event Grid Topic Event Subscription.", diff --git a/avm/res/event-grid/topic/main.bicep b/avm/res/event-grid/topic/main.bicep index be24002758..1d5d5ddee2 100644 --- a/avm/res/event-grid/topic/main.bicep +++ b/avm/res/event-grid/topic/main.bicep @@ -46,42 +46,72 @@ param tags object? @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -var formattedUserAssignedIdentities = reduce(map((managedIdentities.?userAssignedResourcesIds ?? []), (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.?userAssignedResourcesIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(managedIdentities.?userAssignedResourcesIds ?? {}) ? 'UserAssigned' : null) - userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null -} : null +var formattedUserAssignedIdentities = reduce( + map((managedIdentities.?userAssignedResourcesIds ?? []), (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.?userAssignedResourcesIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') + : (!empty(managedIdentities.?userAssignedResourcesIds ?? {}) ? 'UserAssigned' : null) + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null + } + : null var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'EventGrid Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1e241071-0855-49ea-94dc-649edcd759de') - 'EventGrid Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7') - 'EventGrid EventSubscription Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443') - 'EventGrid EventSubscription Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405') + 'EventGrid Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '1e241071-0855-49ea-94dc-649edcd759de' + ) + 'EventGrid Data Sender': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'd5a91429-5739-47e2-a06b-3470a27159e7' + ) + 'EventGrid EventSubscription Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '428e0ff0-5e57-4d9c-a221-2c70d0e0a443' + ) + 'EventGrid EventSubscription Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '2414bbcf-6497-4faf-8c65-045460748405' + ) 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') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: take('46d3xbcp.res.eventgrid-topic.${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' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: take( + '46d3xbcp.res.eventgrid-topic.${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' + } } } } } -} resource topic 'Microsoft.EventGrid/topics@2021-06-01-preview' = { name: name @@ -89,117 +119,152 @@ resource topic 'Microsoft.EventGrid/topics@2021-06-01-preview' = { identity: identity tags: tags properties: { - publicNetworkAccess: !empty(publicNetworkAccess) ? any(publicNetworkAccess) : (!empty(privateEndpoints) && empty(inboundIpRules) ? 'Disabled' : null) + publicNetworkAccess: !empty(publicNetworkAccess) + ? any(publicNetworkAccess) + : (!empty(privateEndpoints) && empty(inboundIpRules) ? 'Disabled' : null) inboundIpRules: (empty(inboundIpRules) ? null : inboundIpRules) disableLocalAuth: disableLocalAuth } } // Event subscriptions -module topics_eventSubscriptions 'event-subscription/main.bicep' = [for (eventSubscription, index) in eventSubscriptions: { - name: '${uniqueString(deployment().name, location)}-EventGrid-Topics-EventSubscriptions-${index}' - params: { - destination: eventSubscription.destination - topicName: topic.name - name: eventSubscription.name - deadLetterDestination: contains(eventSubscriptions, 'deadLetterDestination') ? eventSubscription.deadLetterDestination : {} - deadLetterWithResourceIdentity: contains(eventSubscriptions, 'deadLetterWithResourceIdentity') ? eventSubscription.deadLetterWithResourceIdentity : {} - deliveryWithResourceIdentity: contains(eventSubscriptions, 'deliveryWithResourceIdentity') ? eventSubscription.deliveryWithResourceIdentity : {} - eventDeliverySchema: contains(eventSubscriptions, 'eventDeliverySchema') ? eventSubscription.eventDeliverySchema : 'EventGridSchema' - expirationTimeUtc: contains(eventSubscriptions, 'expirationTimeUtc') ? eventSubscription.expirationTimeUtc : '' - filter: contains(eventSubscriptions, 'filter') ? eventSubscription.filter : {} - labels: contains(eventSubscriptions, 'labels') ? eventSubscription.labels : [] - retryPolicy: contains(eventSubscriptions, 'retryPolicy') ? eventSubscription.retryPolicy : {} +module topics_eventSubscriptions 'event-subscription/main.bicep' = [ + for (eventSubscription, index) in eventSubscriptions: { + name: '${uniqueString(deployment().name, location)}-EventGrid-Topics-EventSubscriptions-${index}' + params: { + destination: eventSubscription.destination + topicName: topic.name + name: eventSubscription.name + deadLetterDestination: contains(eventSubscriptions, 'deadLetterDestination') + ? eventSubscription.deadLetterDestination + : {} + deadLetterWithResourceIdentity: contains(eventSubscriptions, 'deadLetterWithResourceIdentity') + ? eventSubscription.deadLetterWithResourceIdentity + : {} + deliveryWithResourceIdentity: contains(eventSubscriptions, 'deliveryWithResourceIdentity') + ? eventSubscription.deliveryWithResourceIdentity + : {} + eventDeliverySchema: contains(eventSubscriptions, 'eventDeliverySchema') + ? eventSubscription.eventDeliverySchema + : 'EventGridSchema' + expirationTimeUtc: contains(eventSubscriptions, 'expirationTimeUtc') ? eventSubscription.expirationTimeUtc : '' + filter: contains(eventSubscriptions, 'filter') ? eventSubscription.filter : {} + labels: contains(eventSubscriptions, 'labels') ? eventSubscription.labels : [] + retryPolicy: contains(eventSubscriptions, 'retryPolicy') ? eventSubscription.retryPolicy : {} + } } -}] +] -resource topic_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.' +resource topic_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: topic } - scope: topic -} -resource topic_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource topic_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: topic } - scope: topic -}] - -module topic_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-Topic-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(topic.id, '/'))}-${privateEndpoint.?service ?? 'topic'}-${index}' - privateLinkServiceConnections: [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(topic.id, '/'))}-${privateEndpoint.?service ?? 'topic'}-${index}' - properties: { - privateLinkServiceId: topic.id - groupIds: [ - privateEndpoint.?service ?? 'topic' - ] +] + +module topic_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-Topic-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(topic.id, '/'))}-${privateEndpoint.?service ?? 'topic'}-${index}' + privateLinkServiceConnections: [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(topic.id, '/'))}-${privateEndpoint.?service ?? 'topic'}-${index}' + properties: { + privateLinkServiceId: topic.id + groupIds: [ + privateEndpoint.?service ?? 'topic' + ] + } } - } - ] - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(topic.id, '/'))}-${privateEndpoint.?service ?? 'topic'}-${index}' - properties: { - privateLinkServiceId: topic.id - groupIds: [ - privateEndpoint.?service ?? 'topic' + ] + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(topic.id, '/'))}-${privateEndpoint.?service ?? 'topic'}-${index}' + properties: { + privateLinkServiceId: topic.id + groupIds: [ + privateEndpoint.?service ?? 'topic' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] +] -resource topic_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(topic.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource topic_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(topic.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: topic } - scope: topic -}] +] @description('The name of the event grid topic.') output name string = topic.name diff --git a/avm/res/event-grid/topic/main.json b/avm/res/event-grid/topic/main.json index bd6faed608..2dd96899c8 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.25.53.49325", - "templateHash": "17945416734412715410" + "version": "0.26.54.24096", + "templateHash": "1380486990057725745" }, "name": "Event Grid Topics", "description": "This module deploys an Event Grid Topic.", @@ -687,8 +687,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "12495597102731978024" + "version": "0.26.54.24096", + "templateHash": "12645668843865460856" }, "name": "EventGrid Topic Event Subscriptions", "description": "This module deploys an Event Grid Topic Event Subscription.", diff --git a/avm/res/event-grid/topic/tests/e2e/defaults/main.test.bicep b/avm/res/event-grid/topic/tests/e2e/defaults/main.test.bicep index daa75b91f2..e93dd24fb1 100644 --- a/avm/res/event-grid/topic/tests/e2e/defaults/main.test.bicep +++ b/avm/res/event-grid/topic/tests/e2e/defaults/main.test.bicep @@ -35,11 +35,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // 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 +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 + } } -}] +] diff --git a/avm/res/event-grid/topic/tests/e2e/max/main.test.bicep b/avm/res/event-grid/topic/tests/e2e/max/main.test.bicep index 755f0a4793..6c4015fec7 100644 --- a/avm/res/event-grid/topic/tests/e2e/max/main.test.bicep +++ b/avm/res/event-grid/topic/tests/e2e/max/main.test.bicep @@ -62,113 +62,123 @@ 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 - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - eventSubscriptions: [ { - name: '${namePrefix}${serviceShort}001' - expirationTimeUtc: '2099-01-01T11:00:21.715Z' - filter: { - isSubjectCaseSensitive: false - enableAdvancedFilteringOnArrays: true +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 + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } - retryPolicy: { - maxDeliveryAttempts: 10 - eventTimeToLive: '120' - } - eventDeliverySchema: 'CloudEventSchemaV1_0' - destination: { - endpointType: 'StorageQueue' - properties: { - resourceId: nestedDependencies.outputs.storageAccountResourceId - queueMessageTimeToLiveInSeconds: 86400 - queueName: nestedDependencies.outputs.queueName + ] + eventSubscriptions: [ + { + name: '${namePrefix}${serviceShort}001' + expirationTimeUtc: '2099-01-01T11:00:21.715Z' + filter: { + isSubjectCaseSensitive: false + enableAdvancedFilteringOnArrays: true } - } - } ] - inboundIpRules: [ - { - action: 'Allow' - ipMask: '40.74.28.0/23' - } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + retryPolicy: { + maxDeliveryAttempts: 10 + eventTimeToLive: '120' } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + eventDeliverySchema: 'CloudEventSchemaV1_0' + destination: { + endpointType: 'StorageQueue' + properties: { + resourceId: nestedDependencies.outputs.storageAccountResourceId + queueMessageTimeToLiveInSeconds: 86400 + queueName: nestedDependencies.outputs.queueName + } } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + ] + inboundIpRules: [ + { + action: 'Allow' + ipMask: '40.74.28.0/23' + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - subnetResourceId: 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' + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + roleAssignments: [ + { + roleDefinitionIdOrName: 'Owner' + 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' + Role: 'DeploymentValidation' + } + } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/event-grid/topic/tests/e2e/waf-aligned/main.test.bicep b/avm/res/event-grid/topic/tests/e2e/waf-aligned/main.test.bicep index e053ff5149..aec73401ac 100644 --- a/avm/res/event-grid/topic/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/event-grid/topic/tests/e2e/waf-aligned/main.test.bicep @@ -62,74 +62,78 @@ 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 - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - eventSubscriptions: [ { - name: '${namePrefix}${serviceShort}001' - expirationTimeUtc: '2099-01-01T11:00:21.715Z' - filter: { - isSubjectCaseSensitive: false - enableAdvancedFilteringOnArrays: true - } - retryPolicy: { - maxDeliveryAttempts: 10 - eventTimeToLive: '120' +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 + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } - eventDeliverySchema: 'CloudEventSchemaV1_0' - destination: { - endpointType: 'StorageQueue' - properties: { - resourceId: nestedDependencies.outputs.storageAccountResourceId - queueMessageTimeToLiveInSeconds: 86400 - queueName: nestedDependencies.outputs.queueName + ] + eventSubscriptions: [ + { + name: '${namePrefix}${serviceShort}001' + expirationTimeUtc: '2099-01-01T11:00:21.715Z' + filter: { + isSubjectCaseSensitive: false + enableAdvancedFilteringOnArrays: true + } + retryPolicy: { + maxDeliveryAttempts: 10 + eventTimeToLive: '120' + } + eventDeliverySchema: 'CloudEventSchemaV1_0' + destination: { + endpointType: 'StorageQueue' + properties: { + resourceId: nestedDependencies.outputs.storageAccountResourceId + queueMessageTimeToLiveInSeconds: 86400 + queueName: nestedDependencies.outputs.queueName + } } } - } ] - inboundIpRules: [] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - service: 'topic' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + ] + inboundIpRules: [] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + service: 'topic' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/event-hub/namespace/authorization-rule/main.json b/avm/res/event-hub/namespace/authorization-rule/main.json index 6516efc5ac..1e2ad1c42c 100644 --- a/avm/res/event-hub/namespace/authorization-rule/main.json +++ b/avm/res/event-hub/namespace/authorization-rule/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "10638309014943371587" + "version": "0.26.54.24096", + "templateHash": "15327912662565121564" }, "name": "Event Hub Namespace Authorization Rule", "description": "This module deploys an Event Hub Namespace Authorization Rule.", diff --git a/avm/res/event-hub/namespace/disaster-recovery-config/main.json b/avm/res/event-hub/namespace/disaster-recovery-config/main.json index 5e57cbee56..ea59892550 100644 --- a/avm/res/event-hub/namespace/disaster-recovery-config/main.json +++ b/avm/res/event-hub/namespace/disaster-recovery-config/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14933577565840576961" + "version": "0.26.54.24096", + "templateHash": "11732013494690054024" }, "name": "Event Hub Namespace Disaster Recovery Configs", "description": "This module deploys an Event Hub Namespace Disaster Recovery Config.", diff --git a/avm/res/event-hub/namespace/eventhub/authorization-rule/main.json b/avm/res/event-hub/namespace/eventhub/authorization-rule/main.json index 9b5e8a5edc..ecbc4d54d5 100644 --- a/avm/res/event-hub/namespace/eventhub/authorization-rule/main.json +++ b/avm/res/event-hub/namespace/eventhub/authorization-rule/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16757979367783376523" + "version": "0.26.54.24096", + "templateHash": "15301134976738274567" }, "name": "Event Hub Namespace Event Hub Authorization Rules", "description": "This module deploys an Event Hub Namespace Event Hub Authorization Rule.", diff --git a/avm/res/event-hub/namespace/eventhub/consumergroup/main.json b/avm/res/event-hub/namespace/eventhub/consumergroup/main.json index cd74392666..4e7f41aaf5 100644 --- a/avm/res/event-hub/namespace/eventhub/consumergroup/main.json +++ b/avm/res/event-hub/namespace/eventhub/consumergroup/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "697710281814211564" + "version": "0.26.54.24096", + "templateHash": "7757490711276971084" }, "name": "Event Hub Namespace Event Hub Consumer Groups", "description": "This module deploys an Event Hub Namespace Event Hub Consumer Group.", diff --git a/avm/res/event-hub/namespace/eventhub/main.bicep b/avm/res/event-hub/namespace/eventhub/main.bicep index 1cb2cbbf4d..199459adca 100644 --- a/avm/res/event-hub/namespace/eventhub/main.bicep +++ b/avm/res/event-hub/namespace/eventhub/main.bicep @@ -115,8 +115,12 @@ var eventHubProperties = { status: status retentionDescription: { cleanupPolicy: retentionDescriptionCleanupPolicy - retentionTimeInHours: retentionDescriptionCleanupPolicy == 'Delete' ? retentionDescriptionRetentionTimeInHours : null - tombstoneRetentionTimeInHours: retentionDescriptionCleanupPolicy == 'Compact' ? retentionDescriptionTombstoneRetentionTimeInHours : null + retentionTimeInHours: retentionDescriptionCleanupPolicy == 'Delete' + ? retentionDescriptionRetentionTimeInHours + : null + tombstoneRetentionTimeInHours: retentionDescriptionCleanupPolicy == 'Compact' + ? retentionDescriptionTombstoneRetentionTimeInHours + : null } } @@ -139,14 +143,29 @@ var eventHubPropertiesCapture = { } var builtInRoleNames = { - 'Azure Event Hubs Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f526a384-b230-433a-b45c-95f59c4a2dec') - 'Azure Event Hubs Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a638d3c7-ab3a-418d-83e6-5f17a39d4fde') - 'Azure Event Hubs Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2b629674-e913-4c01-ae53-ef4638d8f975') + 'Azure Event Hubs Data Owner': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f526a384-b230-433a-b45c-95f59c4a2dec' + ) + 'Azure Event Hubs Data Receiver': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'a638d3c7-ab3a-418d-83e6-5f17a39d4fde' + ) + 'Azure Event Hubs Data Sender': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '2b629674-e913-4c01-ae53-ef4638d8f975' + ) 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } resource namespace 'Microsoft.EventHub/namespaces@2022-10-01-preview' existing = { @@ -159,48 +178,61 @@ resource eventHub 'Microsoft.EventHub/namespaces/eventhubs@2022-10-01-preview' = properties: captureDescriptionEnabled ? union(eventHubProperties, eventHubPropertiesCapture) : eventHubProperties } -resource eventHub_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.' +resource eventHub_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: eventHub } - scope: eventHub -} -module eventHub_consumergroups 'consumergroup/main.bicep' = [for (consumerGroup, index) in consumergroups: { - name: '${deployment().name}-ConsumerGroup-${index}' - params: { - namespaceName: namespaceName - eventHubName: eventHub.name - name: consumerGroup.name - userMetadata: contains(consumerGroup, 'userMetadata') ? consumerGroup.userMetadata : '' +module eventHub_consumergroups 'consumergroup/main.bicep' = [ + for (consumerGroup, index) in consumergroups: { + name: '${deployment().name}-ConsumerGroup-${index}' + params: { + namespaceName: namespaceName + eventHubName: eventHub.name + name: consumerGroup.name + userMetadata: contains(consumerGroup, 'userMetadata') ? consumerGroup.userMetadata : '' + } } -}] - -module eventHub_authorizationRules 'authorization-rule/main.bicep' = [for (authorizationRule, index) in authorizationRules: { - name: '${deployment().name}-AuthRule-${index}' - params: { - namespaceName: namespaceName - eventHubName: eventHub.name - name: authorizationRule.name - rights: contains(authorizationRule, 'rights') ? authorizationRule.rights : [] +] + +module eventHub_authorizationRules 'authorization-rule/main.bicep' = [ + for (authorizationRule, index) in authorizationRules: { + name: '${deployment().name}-AuthRule-${index}' + params: { + namespaceName: namespaceName + eventHubName: eventHub.name + name: authorizationRule.name + rights: contains(authorizationRule, 'rights') ? authorizationRule.rights : [] + } } -}] - -resource eventHub_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(eventHub.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +] + +resource eventHub_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(eventHub.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: eventHub } - scope: eventHub -}] +] @description('The name of the event hub.') output name string = eventHub.name diff --git a/avm/res/event-hub/namespace/eventhub/main.json b/avm/res/event-hub/namespace/eventhub/main.json index 57543ef237..d152f71273 100644 --- a/avm/res/event-hub/namespace/eventhub/main.json +++ b/avm/res/event-hub/namespace/eventhub/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "8657514846937945810" + "version": "0.26.54.24096", + "templateHash": "14538170733088329405" }, "name": "Event Hub Namespace Event Hubs", "description": "This module deploys an Event Hub Namespace Event Hub.", @@ -416,8 +416,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "697710281814211564" + "version": "0.26.54.24096", + "templateHash": "7757490711276971084" }, "name": "Event Hub Namespace Event Hub Consumer Groups", "description": "This module deploys an Event Hub Namespace Event Hub Consumer Group.", @@ -520,8 +520,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16757979367783376523" + "version": "0.26.54.24096", + "templateHash": "15301134976738274567" }, "name": "Event Hub Namespace Event Hub Authorization Rules", "description": "This module deploys an Event Hub Namespace Event Hub Authorization Rule.", diff --git a/avm/res/event-hub/namespace/main.bicep b/avm/res/event-hub/namespace/main.bicep index ace3641cec..a6cda2cc83 100644 --- a/avm/res/event-hub/namespace/main.bicep +++ b/avm/res/event-hub/namespace/main.bicep @@ -106,55 +106,88 @@ param disasterRecoveryConfig object = {} var maximumThroughputUnitsVar = !isAutoInflateEnabled ? 0 : maximumThroughputUnits -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' : 'None') - userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null -} : null +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' : 'None') + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null + } + : null var builtInRoleNames = { - 'Azure Event Hubs Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f526a384-b230-433a-b45c-95f59c4a2dec') - 'Azure Event Hubs Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a638d3c7-ab3a-418d-83e6-5f17a39d4fde') - 'Azure Event Hubs Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2b629674-e913-4c01-ae53-ef4638d8f975') + 'Azure Event Hubs Data Owner': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f526a384-b230-433a-b45c-95f59c4a2dec' + ) + 'Azure Event Hubs Data Receiver': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'a638d3c7-ab3a-418d-83e6-5f17a39d4fde' + ) + 'Azure Event Hubs Data Sender': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '2b629674-e913-4c01-ae53-ef4638d8f975' + ) 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId)) { - name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) - scope: resourceGroup(split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4]) - - resource cMKKey 'keys@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { - name: customerManagedKey.?keyName ?? 'dummyKey' +resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = + if (!empty(customerManagedKey.?keyVaultResourceId)) { + name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) + scope: resourceGroup( + split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], + split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4] + ) + + resource cMKKey 'keys@2023-02-01' existing = + if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { + name: customerManagedKey.?keyName ?? 'dummyKey' + } } -} -resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { - name: last(split(customerManagedKey.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) - scope: resourceGroup(split((customerManagedKey.?userAssignedIdentityResourceId ?? '//'), '/')[2], split((customerManagedKey.?userAssignedIdentityResourceId ?? '////'), '/')[4]) -} +resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = + if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { + name: last(split(customerManagedKey.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) + scope: resourceGroup( + split((customerManagedKey.?userAssignedIdentityResourceId ?? '//'), '/')[2], + split((customerManagedKey.?userAssignedIdentityResourceId ?? '////'), '/')[4] + ) + } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.eventhub-namespace.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.eventhub-namespace.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource eventHubNamespace 'Microsoft.EventHub/namespaces@2022-10-01-preview' = { name: name @@ -168,182 +201,260 @@ resource eventHubNamespace 'Microsoft.EventHub/namespaces@2022-10-01-preview' = } properties: { disableLocalAuth: disableLocalAuth - encryption: !empty(customerManagedKey) ? { - keySource: 'Microsoft.KeyVault' - keyVaultProperties: [ - { - identity: !empty(customerManagedKey.?userAssignedIdentityResourceId) ? { - userAssignedIdentity: cMKUserAssignedIdentity.id - } : null - keyName: customerManagedKey!.keyName - keyVaultUri: cMKKeyVault.properties.vaultUri - keyVersion: !empty(customerManagedKey.?keyVersion ?? '') ? customerManagedKey!.keyVersion : last(split(cMKKeyVault::cMKKey.properties.keyUriWithVersion, '/')) + encryption: !empty(customerManagedKey) + ? { + keySource: 'Microsoft.KeyVault' + keyVaultProperties: [ + { + identity: !empty(customerManagedKey.?userAssignedIdentityResourceId) + ? { + userAssignedIdentity: cMKUserAssignedIdentity.id + } + : null + keyName: customerManagedKey!.keyName + keyVaultUri: cMKKeyVault.properties.vaultUri + keyVersion: !empty(customerManagedKey.?keyVersion ?? '') + ? customerManagedKey!.keyVersion + : last(split(cMKKeyVault::cMKKey.properties.keyUriWithVersion, '/')) + } + ] + requireInfrastructureEncryption: requireInfrastructureEncryption } - ] - requireInfrastructureEncryption: requireInfrastructureEncryption - } : null + : null isAutoInflateEnabled: isAutoInflateEnabled kafkaEnabled: kafkaEnabled maximumThroughputUnits: maximumThroughputUnitsVar minimumTlsVersion: minimumTlsVersion - publicNetworkAccess: contains(networkRuleSets, 'publicNetworkAccess') ? networkRuleSets.publicNetworkAccess : (!empty(privateEndpoints) && empty(networkRuleSets) ? 'Disabled' : publicNetworkAccess) + publicNetworkAccess: contains(networkRuleSets, 'publicNetworkAccess') + ? networkRuleSets.publicNetworkAccess + : (!empty(privateEndpoints) && empty(networkRuleSets) ? 'Disabled' : publicNetworkAccess) zoneRedundant: zoneRedundant } } -module eventHubNamespace_authorizationRules 'authorization-rule/main.bicep' = [for (authorizationRule, index) in authorizationRules: { - name: '${uniqueString(deployment().name, location)}-EvhbNamespace-AuthRule-${index}' - params: { - namespaceName: eventHubNamespace.name - name: authorizationRule.name - rights: contains(authorizationRule, 'rights') ? authorizationRule.rights : [] +module eventHubNamespace_authorizationRules 'authorization-rule/main.bicep' = [ + for (authorizationRule, index) in authorizationRules: { + name: '${uniqueString(deployment().name, location)}-EvhbNamespace-AuthRule-${index}' + params: { + namespaceName: eventHubNamespace.name + name: authorizationRule.name + rights: contains(authorizationRule, 'rights') ? authorizationRule.rights : [] + } } -}] - -module eventHubNamespace_disasterRecoveryConfig 'disaster-recovery-config/main.bicep' = if (!empty(disasterRecoveryConfig)) { - name: '${uniqueString(deployment().name, location)}-EvhbNamespace-DisRecConfig' - params: { - namespaceName: eventHubNamespace.name - name: disasterRecoveryConfig.name - partnerNamespaceId: contains(disasterRecoveryConfig, 'partnerNamespaceId') ? disasterRecoveryConfig.partnerNamespaceId : '' +] + +module eventHubNamespace_disasterRecoveryConfig 'disaster-recovery-config/main.bicep' = + if (!empty(disasterRecoveryConfig)) { + name: '${uniqueString(deployment().name, location)}-EvhbNamespace-DisRecConfig' + params: { + namespaceName: eventHubNamespace.name + name: disasterRecoveryConfig.name + partnerNamespaceId: contains(disasterRecoveryConfig, 'partnerNamespaceId') + ? disasterRecoveryConfig.partnerNamespaceId + : '' + } } -} -module eventHubNamespace_eventhubs 'eventhub/main.bicep' = [for (eventHub, index) in eventhubs: { - name: '${uniqueString(deployment().name, location)}-EvhbNamespace-EventHub-${index}' - params: { - namespaceName: eventHubNamespace.name - name: eventHub.name - authorizationRules: contains(eventHub, 'authorizationRules') ? eventHub.authorizationRules : [ - { - name: 'RootManageSharedAccessKey' - rights: [ - 'Listen' - 'Manage' - 'Send' - ] - } - ] - captureDescriptionDestinationArchiveNameFormat: contains(eventHub, 'captureDescriptionDestinationArchiveNameFormat') ? eventHub.captureDescriptionDestinationArchiveNameFormat : '{Namespace}/{EventHub}/{PartitionId}/{Year}/{Month}/{Day}/{Hour}/{Minute}/{Second}' - captureDescriptionDestinationBlobContainer: contains(eventHub, 'captureDescriptionDestinationBlobContainer') ? eventHub.captureDescriptionDestinationBlobContainer : '' - captureDescriptionDestinationName: contains(eventHub, 'captureDescriptionDestinationName') ? eventHub.captureDescriptionDestinationName : 'EventHubArchive.AzureBlockBlob' - captureDescriptionDestinationStorageAccountResourceId: contains(eventHub, 'captureDescriptionDestinationStorageAccountResourceId') ? eventHub.captureDescriptionDestinationStorageAccountResourceId : '' - captureDescriptionEnabled: contains(eventHub, 'captureDescriptionEnabled') ? eventHub.captureDescriptionEnabled : false - captureDescriptionEncoding: contains(eventHub, 'captureDescriptionEncoding') ? eventHub.captureDescriptionEncoding : 'Avro' - captureDescriptionIntervalInSeconds: contains(eventHub, 'captureDescriptionIntervalInSeconds') ? eventHub.captureDescriptionIntervalInSeconds : 300 - captureDescriptionSizeLimitInBytes: contains(eventHub, 'captureDescriptionSizeLimitInBytes') ? eventHub.captureDescriptionSizeLimitInBytes : 314572800 - captureDescriptionSkipEmptyArchives: contains(eventHub, 'captureDescriptionSkipEmptyArchives') ? eventHub.captureDescriptionSkipEmptyArchives : false - consumergroups: contains(eventHub, 'consumergroups') ? eventHub.consumergroups : [] - lock: eventHub.?lock ?? lock - messageRetentionInDays: contains(eventHub, 'messageRetentionInDays') ? eventHub.messageRetentionInDays : 1 - partitionCount: contains(eventHub, 'partitionCount') ? eventHub.partitionCount : 2 - roleAssignments: contains(eventHub, 'roleAssignments') ? eventHub.roleAssignments : [] - status: contains(eventHub, 'status') ? eventHub.status : 'Active' - retentionDescriptionCleanupPolicy: contains(eventHub, 'retentionDescriptionCleanupPolicy') ? eventHub.retentionDescriptionCleanupPolicy : 'Delete' - retentionDescriptionRetentionTimeInHours: contains(eventHub, 'retentionDescriptionRetentionTimeInHours') ? eventHub.retentionDescriptionRetentionTimeInHours : 1 - retentionDescriptionTombstoneRetentionTimeInHours: contains(eventHub, 'retentionDescriptionTombstoneRetentionTimeInHours') ? eventHub.retentionDescriptionTombstoneRetentionTimeInHours : 1 +module eventHubNamespace_eventhubs 'eventhub/main.bicep' = [ + for (eventHub, index) in eventhubs: { + name: '${uniqueString(deployment().name, location)}-EvhbNamespace-EventHub-${index}' + params: { + namespaceName: eventHubNamespace.name + name: eventHub.name + authorizationRules: contains(eventHub, 'authorizationRules') + ? eventHub.authorizationRules + : [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + ] + captureDescriptionDestinationArchiveNameFormat: contains( + eventHub, + 'captureDescriptionDestinationArchiveNameFormat' + ) + ? eventHub.captureDescriptionDestinationArchiveNameFormat + : '{Namespace}/{EventHub}/{PartitionId}/{Year}/{Month}/{Day}/{Hour}/{Minute}/{Second}' + captureDescriptionDestinationBlobContainer: contains(eventHub, 'captureDescriptionDestinationBlobContainer') + ? eventHub.captureDescriptionDestinationBlobContainer + : '' + captureDescriptionDestinationName: contains(eventHub, 'captureDescriptionDestinationName') + ? eventHub.captureDescriptionDestinationName + : 'EventHubArchive.AzureBlockBlob' + captureDescriptionDestinationStorageAccountResourceId: contains( + eventHub, + 'captureDescriptionDestinationStorageAccountResourceId' + ) + ? eventHub.captureDescriptionDestinationStorageAccountResourceId + : '' + captureDescriptionEnabled: contains(eventHub, 'captureDescriptionEnabled') + ? eventHub.captureDescriptionEnabled + : false + captureDescriptionEncoding: contains(eventHub, 'captureDescriptionEncoding') + ? eventHub.captureDescriptionEncoding + : 'Avro' + captureDescriptionIntervalInSeconds: contains(eventHub, 'captureDescriptionIntervalInSeconds') + ? eventHub.captureDescriptionIntervalInSeconds + : 300 + captureDescriptionSizeLimitInBytes: contains(eventHub, 'captureDescriptionSizeLimitInBytes') + ? eventHub.captureDescriptionSizeLimitInBytes + : 314572800 + captureDescriptionSkipEmptyArchives: contains(eventHub, 'captureDescriptionSkipEmptyArchives') + ? eventHub.captureDescriptionSkipEmptyArchives + : false + consumergroups: contains(eventHub, 'consumergroups') ? eventHub.consumergroups : [] + lock: eventHub.?lock ?? lock + messageRetentionInDays: contains(eventHub, 'messageRetentionInDays') ? eventHub.messageRetentionInDays : 1 + partitionCount: contains(eventHub, 'partitionCount') ? eventHub.partitionCount : 2 + roleAssignments: contains(eventHub, 'roleAssignments') ? eventHub.roleAssignments : [] + status: contains(eventHub, 'status') ? eventHub.status : 'Active' + retentionDescriptionCleanupPolicy: contains(eventHub, 'retentionDescriptionCleanupPolicy') + ? eventHub.retentionDescriptionCleanupPolicy + : 'Delete' + retentionDescriptionRetentionTimeInHours: contains(eventHub, 'retentionDescriptionRetentionTimeInHours') + ? eventHub.retentionDescriptionRetentionTimeInHours + : 1 + retentionDescriptionTombstoneRetentionTimeInHours: contains( + eventHub, + 'retentionDescriptionTombstoneRetentionTimeInHours' + ) + ? eventHub.retentionDescriptionTombstoneRetentionTimeInHours + : 1 + } } -}] - -module eventHubNamespace_networkRuleSet 'network-rule-set/main.bicep' = if (!empty(networkRuleSets) || !empty(privateEndpoints)) { - name: '${uniqueString(deployment().name, location)}-EvhbNamespace-NetworkRuleSet' - params: { - namespaceName: eventHubNamespace.name - publicNetworkAccess: contains(networkRuleSets, 'publicNetworkAccess') ? networkRuleSets.publicNetworkAccess : (!empty(privateEndpoints) && empty(networkRuleSets) ? 'Disabled' : 'Enabled') - defaultAction: contains(networkRuleSets, 'defaultAction') ? networkRuleSets.defaultAction : 'Allow' - trustedServiceAccessEnabled: networkRuleSets.?trustedServiceAccessEnabled - ipRules: contains(networkRuleSets, 'ipRules') ? networkRuleSets.ipRules : [] - virtualNetworkRules: contains(networkRuleSets, 'virtualNetworkRules') ? networkRuleSets.virtualNetworkRules : [] +] + +module eventHubNamespace_networkRuleSet 'network-rule-set/main.bicep' = + if (!empty(networkRuleSets) || !empty(privateEndpoints)) { + name: '${uniqueString(deployment().name, location)}-EvhbNamespace-NetworkRuleSet' + params: { + namespaceName: eventHubNamespace.name + publicNetworkAccess: contains(networkRuleSets, 'publicNetworkAccess') + ? networkRuleSets.publicNetworkAccess + : (!empty(privateEndpoints) && empty(networkRuleSets) ? 'Disabled' : 'Enabled') + defaultAction: contains(networkRuleSets, 'defaultAction') ? networkRuleSets.defaultAction : 'Allow' + trustedServiceAccessEnabled: networkRuleSets.?trustedServiceAccessEnabled + ipRules: contains(networkRuleSets, 'ipRules') ? networkRuleSets.ipRules : [] + virtualNetworkRules: contains(networkRuleSets, 'virtualNetworkRules') ? networkRuleSets.virtualNetworkRules : [] + } } -} -module eventHubNamespace_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-EventHubNamespace-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(eventHubNamespace.id, '/'))}-${privateEndpoint.?service ?? 'namespace'}-${index}' - privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(eventHubNamespace.id, '/'))}-${privateEndpoint.?service ?? 'namespace'}-${index}' - properties: { - privateLinkServiceId: eventHubNamespace.id - groupIds: [ - privateEndpoint.?service ?? 'namespace' +module eventHubNamespace_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-EventHubNamespace-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(eventHubNamespace.id, '/'))}-${privateEndpoint.?service ?? 'namespace'}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(eventHubNamespace.id, '/'))}-${privateEndpoint.?service ?? 'namespace'}-${index}' + properties: { + privateLinkServiceId: eventHubNamespace.id + groupIds: [ + privateEndpoint.?service ?? 'namespace' + ] + } + } ] - } - } - ] : null - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(eventHubNamespace.id, '/'))}-${privateEndpoint.?service ?? 'namespace'}-${index}' - properties: { - privateLinkServiceId: eventHubNamespace.id - groupIds: [ - privateEndpoint.?service ?? 'namespace' + : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(eventHubNamespace.id, '/'))}-${privateEndpoint.?service ?? 'namespace'}-${index}' + properties: { + privateLinkServiceId: eventHubNamespace.id + groupIds: [ + privateEndpoint.?service ?? 'namespace' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] +] -resource eventHubNamespace_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(eventHubNamespace.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource eventHubNamespace_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(eventHubNamespace.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: eventHubNamespace } - scope: eventHubNamespace -}] +] -resource eventHubNamespace_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.' +resource eventHubNamespace_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: eventHubNamespace } - scope: eventHubNamespace -} -resource eventHubNamespace_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource eventHubNamespace_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: eventHubNamespace } - scope: eventHubNamespace -}] +] @description('The name of the eventspace.') output name string = eventHubNamespace.name @@ -361,7 +472,9 @@ output systemAssignedMIPrincipalId string = eventHubNamespace.?identity.?princip output location string = eventHubNamespace.location @description('The Resources IDs of the EventHubs within this eventspace.') -output eventHubResourceIds array = [for index in range(0, length(eventhubs ?? [])): eventHubNamespace_eventhubs[index].outputs.resourceId] +output eventHubResourceIds array = [ + for index in range(0, length(eventhubs ?? [])): eventHubNamespace_eventhubs[index].outputs.resourceId +] // =============== // // Definitions // diff --git a/avm/res/event-hub/namespace/main.json b/avm/res/event-hub/namespace/main.json index fa65131a62..95d0847f8a 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.25.53.49325", - "templateHash": "11007166139796021582" + "version": "0.26.54.24096", + "templateHash": "5884251970985873966" }, "name": "Event Hub Namespaces", "description": "This module deploys an Event Hub Namespace.", @@ -854,8 +854,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "10638309014943371587" + "version": "0.26.54.24096", + "templateHash": "15327912662565121564" }, "name": "Event Hub Namespace Authorization Rule", "description": "This module deploys an Event Hub Namespace Authorization Rule.", @@ -951,8 +951,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14933577565840576961" + "version": "0.26.54.24096", + "templateHash": "11732013494690054024" }, "name": "Event Hub Namespace Disaster Recovery Configs", "description": "This module deploys an Event Hub Namespace Disaster Recovery Config.", @@ -1067,8 +1067,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "8657514846937945810" + "version": "0.26.54.24096", + "templateHash": "14538170733088329405" }, "name": "Event Hub Namespace Event Hubs", "description": "This module deploys an Event Hub Namespace Event Hub.", @@ -1478,8 +1478,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "697710281814211564" + "version": "0.26.54.24096", + "templateHash": "7757490711276971084" }, "name": "Event Hub Namespace Event Hub Consumer Groups", "description": "This module deploys an Event Hub Namespace Event Hub Consumer Group.", @@ -1582,8 +1582,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16757979367783376523" + "version": "0.26.54.24096", + "templateHash": "15301134976738274567" }, "name": "Event Hub Namespace Event Hub Authorization Rules", "description": "This module deploys an Event Hub Namespace Event Hub Authorization Rule.", @@ -1718,8 +1718,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11239292624069957748" + "version": "0.26.54.24096", + "templateHash": "3984181780336367181" }, "name": "Event Hub Namespace Network Rule Sets", "description": "This module deploys an Event Hub Namespace Network Rule Set.", diff --git a/avm/res/event-hub/namespace/network-rule-set/main.bicep b/avm/res/event-hub/namespace/network-rule-set/main.bicep index 925095ca39..382e1a8e3e 100644 --- a/avm/res/event-hub/namespace/network-rule-set/main.bicep +++ b/avm/res/event-hub/namespace/network-rule-set/main.bicep @@ -29,14 +29,20 @@ param virtualNetworkRules array = [] param ipRules array = [] @description('Optional. The name of the network ruleset.') - param networkRuleSetName string = 'default' +param networkRuleSetName string = 'default' -var networkRules = [for (virtualNetworkRule, index) in virtualNetworkRules: { - ignoreMissingVnetServiceEndpoint: contains(virtualNetworkRule, 'ignoreMissingVnetServiceEndpoint') ? virtualNetworkRule.ignoreMissingVnetServiceEndpoint : null - subnet: contains(virtualNetworkRule, 'subnetResourceId') ? { - id: virtualNetworkRule.subnetResourceId - } : null -}] +var networkRules = [ + for (virtualNetworkRule, index) in virtualNetworkRules: { + ignoreMissingVnetServiceEndpoint: contains(virtualNetworkRule, 'ignoreMissingVnetServiceEndpoint') + ? virtualNetworkRule.ignoreMissingVnetServiceEndpoint + : null + subnet: contains(virtualNetworkRule, 'subnetResourceId') + ? { + id: virtualNetworkRule.subnetResourceId + } + : null + } +] resource namespace 'Microsoft.EventHub/namespaces@2022-10-01-preview' existing = { name: namespaceName @@ -47,7 +53,9 @@ resource networkRuleSet 'Microsoft.EventHub/namespaces/networkRuleSets@2022-10-0 parent: namespace properties: { publicNetworkAccess: publicNetworkAccess - defaultAction: publicNetworkAccess == 'Disabled' ? null : (!empty(ipRules) || !empty(virtualNetworkRules) ? 'Deny' : defaultAction) + defaultAction: publicNetworkAccess == 'Disabled' + ? null + : (!empty(ipRules) || !empty(virtualNetworkRules) ? 'Deny' : defaultAction) trustedServiceAccessEnabled: trustedServiceAccessEnabled ipRules: publicNetworkAccess == 'Disabled' ? null : ipRules virtualNetworkRules: publicNetworkAccess == 'Disabled' ? null : networkRules diff --git a/avm/res/event-hub/namespace/network-rule-set/main.json b/avm/res/event-hub/namespace/network-rule-set/main.json index 923c335e93..2a82bd5fc8 100644 --- a/avm/res/event-hub/namespace/network-rule-set/main.json +++ b/avm/res/event-hub/namespace/network-rule-set/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11239292624069957748" + "version": "0.26.54.24096", + "templateHash": "3984181780336367181" }, "name": "Event Hub Namespace Network Rule Sets", "description": "This module deploys an Event Hub Namespace Network Rule Set.", diff --git a/avm/res/event-hub/namespace/tests/e2e/defaults/main.test.bicep b/avm/res/event-hub/namespace/tests/e2e/defaults/main.test.bicep index b6a55d3ace..1e04339dfb 100644 --- a/avm/res/event-hub/namespace/tests/e2e/defaults/main.test.bicep +++ b/avm/res/event-hub/namespace/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 +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 + } } -}] +] diff --git a/avm/res/event-hub/namespace/tests/e2e/encr/dependencies.bicep b/avm/res/event-hub/namespace/tests/e2e/encr/dependencies.bicep index dab158fd15..6c4085b1e5 100644 --- a/avm/res/event-hub/namespace/tests/e2e/encr/dependencies.bicep +++ b/avm/res/event-hub/namespace/tests/e2e/encr/dependencies.bicep @@ -69,7 +69,10 @@ resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { properties: { principalId: managedIdentity.properties.principalId // Key Vault Crypto User - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '12338af0-0e69-4776-bea7-57ae8d297424' + ) principalType: 'ServicePrincipal' } } diff --git a/avm/res/event-hub/namespace/tests/e2e/encr/main.test.bicep b/avm/res/event-hub/namespace/tests/e2e/encr/main.test.bicep index d4296b83d8..ae8a447877 100644 --- a/avm/res/event-hub/namespace/tests/e2e/encr/main.test.bicep +++ b/avm/res/event-hub/namespace/tests/e2e/encr/main.test.bicep @@ -3,7 +3,6 @@ targetScope = 'subscription' metadata name = 'Using encryption with Customer-Managed-Key' metadata description = 'This instance deploys the module using Customer-Managed-Keys using a User-Assigned Identity to access the Customer-Managed-Key secret.' - // ========== // // Parameters // // ========== // diff --git a/avm/res/event-hub/namespace/tests/e2e/max/main.test.bicep b/avm/res/event-hub/namespace/tests/e2e/max/main.test.bicep index 4433a3e1a0..b4f2b5c6c3 100644 --- a/avm/res/event-hub/namespace/tests/e2e/max/main.test.bicep +++ b/avm/res/event-hub/namespace/tests/e2e/max/main.test.bicep @@ -59,178 +59,183 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t // 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 - zoneRedundant: true - skuName: 'Standard' - skuCapacity: 2 - authorizationRules: [ - { - name: 'RootManageSharedAccessKey' - rights: [ - 'Listen' - 'Manage' - 'Send' - ] - } - { - name: 'SendListenAccess' - rights: [ - 'Listen' - 'Send' - ] - } - ] - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - eventhubs: [ - { - name: '${namePrefix}-az-evh-x-001' - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - ] +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 + zoneRedundant: true + skuName: 'Standard' + skuCapacity: 2 + authorizationRules: [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + { + name: 'SendListenAccess' + rights: [ + 'Listen' + 'Send' + ] + } + ] + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + eventhubs: [ + { + name: '${namePrefix}-az-evh-x-001' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + } + { + name: '${namePrefix}-az-evh-x-002' + authorizationRules: [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + { + name: 'SendListenAccess' + rights: [ + 'Listen' + 'Send' + ] + } + ] + captureDescriptionDestinationArchiveNameFormat: '{Namespace}/{EventHub}/{PartitionId}/{Year}/{Month}/{Day}/{Hour}/{Minute}/{Second}' + captureDescriptionDestinationBlobContainer: 'eventhub' + captureDescriptionDestinationName: 'EventHubArchive.AzureBlockBlob' + captureDescriptionDestinationStorageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + captureDescriptionEnabled: true + captureDescriptionEncoding: 'Avro' + captureDescriptionIntervalInSeconds: 300 + captureDescriptionSizeLimitInBytes: 314572800 + captureDescriptionSkipEmptyArchives: true + consumergroups: [ + { + name: 'custom' + userMetadata: 'customMetadata' + } + ] + messageRetentionInDays: 1 + partitionCount: 2 + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + status: 'Active' + retentionDescriptionCleanupPolicy: 'Delete' + retentionDescriptionRetentionTimeInHours: 3 + } + { + name: '${namePrefix}-az-evh-x-003' + retentionDescriptionCleanupPolicy: 'Compact' + retentionDescriptionTombstoneRetentionTimeInHours: 24 + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - name: '${namePrefix}-az-evh-x-002' - authorizationRules: [ + networkRuleSets: { + defaultAction: 'Deny' + ipRules: [ { - name: 'RootManageSharedAccessKey' - rights: [ - 'Listen' - 'Manage' - 'Send' - ] - } - { - name: 'SendListenAccess' - rights: [ - 'Listen' - 'Send' - ] + action: 'Allow' + ipMask: '10.10.10.10' } ] - captureDescriptionDestinationArchiveNameFormat: '{Namespace}/{EventHub}/{PartitionId}/{Year}/{Month}/{Day}/{Hour}/{Minute}/{Second}' - captureDescriptionDestinationBlobContainer: 'eventhub' - captureDescriptionDestinationName: 'EventHubArchive.AzureBlockBlob' - captureDescriptionDestinationStorageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId - captureDescriptionEnabled: true - captureDescriptionEncoding: 'Avro' - captureDescriptionIntervalInSeconds: 300 - captureDescriptionSizeLimitInBytes: 314572800 - captureDescriptionSkipEmptyArchives: true - consumergroups: [ + trustedServiceAccessEnabled: false + publicNetworkAccess: 'Disabled' + virtualNetworkRules: [ { - name: 'custom' - userMetadata: 'customMetadata' + ignoreMissingVnetServiceEndpoint: true + subnetResourceId: nestedDependencies.outputs.subnetResourceId } ] - messageRetentionInDays: 1 - partitionCount: 2 - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - ] - status: 'Active' - retentionDescriptionCleanupPolicy: 'Delete' - retentionDescriptionRetentionTimeInHours: 3 - } - { - name: '${namePrefix}-az-evh-x-003' - retentionDescriptionCleanupPolicy: 'Compact' - retentionDescriptionTombstoneRetentionTimeInHours: 24 } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - networkRuleSets: { - defaultAction: 'Deny' - ipRules: [ + privateEndpoints: [ { - action: 'Allow' - ipMask: '10.10.10.10' + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + service: 'namespace' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } ] - trustedServiceAccessEnabled: false - publicNetworkAccess: 'Disabled' - virtualNetworkRules: [ + roleAssignments: [ { - ignoreMissingVnetServiceEndpoint: true - subnetResourceId: nestedDependencies.outputs.subnetResourceId + 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' } ] - } - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId ] - service: 'namespace' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } - ] - 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' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - managedIdentities: { - systemAssigned: true - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + kafkaEnabled: true + disableLocalAuth: true + isAutoInflateEnabled: true + minimumTlsVersion: '1.2' + maximumThroughputUnits: 4 + publicNetworkAccess: 'Disabled' } - kafkaEnabled: true - disableLocalAuth: true - isAutoInflateEnabled: true - minimumTlsVersion: '1.2' - maximumThroughputUnits: 4 - publicNetworkAccess: 'Disabled' } -}] +] diff --git a/avm/res/event-hub/namespace/tests/e2e/waf-aligned/main.test.bicep b/avm/res/event-hub/namespace/tests/e2e/waf-aligned/main.test.bicep index 607e156738..cf65bb6f5e 100644 --- a/avm/res/event-hub/namespace/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/event-hub/namespace/tests/e2e/waf-aligned/main.test.bicep @@ -58,135 +58,137 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t // 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 - zoneRedundant: true - skuName: 'Standard' - skuCapacity: 2 - authorizationRules: [ - { - name: 'RootManageSharedAccessKey' - rights: [ - 'Listen' - 'Manage' - 'Send' - ] - } - { - name: 'SendListenAccess' - rights: [ - 'Listen' - 'Send' - ] - } - ] - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - eventhubs: [ - { - name: '${namePrefix}-az-evh-x-001' - } - { - name: '${namePrefix}-az-evh-x-002' - authorizationRules: [ - { - name: 'RootManageSharedAccessKey' - rights: [ - 'Listen' - 'Manage' - 'Send' - ] - } +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 + zoneRedundant: true + skuName: 'Standard' + skuCapacity: 2 + authorizationRules: [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + { + name: 'SendListenAccess' + rights: [ + 'Listen' + 'Send' + ] + } + ] + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + eventhubs: [ + { + name: '${namePrefix}-az-evh-x-001' + } + { + name: '${namePrefix}-az-evh-x-002' + authorizationRules: [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + { + name: 'SendListenAccess' + rights: [ + 'Listen' + 'Send' + ] + } + ] + captureDescriptionDestinationArchiveNameFormat: '{Namespace}/{EventHub}/{PartitionId}/{Year}/{Month}/{Day}/{Hour}/{Minute}/{Second}' + captureDescriptionDestinationBlobContainer: 'eventhub' + captureDescriptionDestinationName: 'EventHubArchive.AzureBlockBlob' + captureDescriptionDestinationStorageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + captureDescriptionEnabled: true + captureDescriptionEncoding: 'Avro' + captureDescriptionIntervalInSeconds: 300 + captureDescriptionSizeLimitInBytes: 314572800 + captureDescriptionSkipEmptyArchives: true + consumergroups: [ + { + name: 'custom' + userMetadata: 'customMetadata' + } + ] + messageRetentionInDays: 1 + partitionCount: 2 + status: 'Active' + retentionDescriptionCleanupPolicy: 'Delete' + retentionDescriptionRetentionTimeInHours: 3 + } + { + name: '${namePrefix}-az-evh-x-003' + retentionDescriptionCleanupPolicy: 'Compact' + retentionDescriptionTombstoneRetentionTimeInHours: 24 + } + ] + networkRuleSets: { + defaultAction: 'Deny' + ipRules: [ { - name: 'SendListenAccess' - rights: [ - 'Listen' - 'Send' - ] + action: 'Allow' + ipMask: '10.10.10.10' } ] - captureDescriptionDestinationArchiveNameFormat: '{Namespace}/{EventHub}/{PartitionId}/{Year}/{Month}/{Day}/{Hour}/{Minute}/{Second}' - captureDescriptionDestinationBlobContainer: 'eventhub' - captureDescriptionDestinationName: 'EventHubArchive.AzureBlockBlob' - captureDescriptionDestinationStorageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId - captureDescriptionEnabled: true - captureDescriptionEncoding: 'Avro' - captureDescriptionIntervalInSeconds: 300 - captureDescriptionSizeLimitInBytes: 314572800 - captureDescriptionSkipEmptyArchives: true - consumergroups: [ + trustedServiceAccessEnabled: false + virtualNetworkRules: [ { - name: 'custom' - userMetadata: 'customMetadata' + ignoreMissingVnetServiceEndpoint: true + subnetResourceId: nestedDependencies.outputs.subnetResourceId } ] - messageRetentionInDays: 1 - partitionCount: 2 - status: 'Active' - retentionDescriptionCleanupPolicy: 'Delete' - retentionDescriptionRetentionTimeInHours: 3 - } - { - name: '${namePrefix}-az-evh-x-003' - retentionDescriptionCleanupPolicy: 'Compact' - retentionDescriptionTombstoneRetentionTimeInHours: 24 } - ] - networkRuleSets: { - defaultAction: 'Deny' - ipRules: [ - { - action: 'Allow' - ipMask: '10.10.10.10' - } - ] - trustedServiceAccessEnabled: false - virtualNetworkRules: [ + privateEndpoints: [ { - ignoreMissingVnetServiceEndpoint: true + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } ] - } - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } + kafkaEnabled: true + disableLocalAuth: true + isAutoInflateEnabled: true + minimumTlsVersion: '1.2' + maximumThroughputUnits: 4 + publicNetworkAccess: 'Disabled' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - kafkaEnabled: true - disableLocalAuth: true - isAutoInflateEnabled: true - minimumTlsVersion: '1.2' - maximumThroughputUnits: 4 - publicNetworkAccess: 'Disabled' - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/health-bot/health-bot/main.bicep b/avm/res/health-bot/health-bot/main.bicep index 646bd61273..cbf4ac9fb9 100644 --- a/avm/res/health-bot/health-bot/main.bicep +++ b/avm/res/health-bot/health-bot/main.bicep @@ -31,38 +31,51 @@ param tags object? @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -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: !empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null - userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null -} : null +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: !empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null + } + : 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.healthbot-healthbot.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.healthbot-healthbot.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource healthBot 'Microsoft.HealthBot/healthBots@2022-08-08' = { name: name @@ -75,28 +88,37 @@ resource healthBot 'Microsoft.HealthBot/healthBots@2022-08-08' = { properties: {} } -resource healthBot_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.' +resource healthBot_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: healthBot } - scope: healthBot -} -resource healthBot_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(healthBot.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource healthBot_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(healthBot.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: healthBot } - scope: healthBot -}] +] @description('The resource group the health bot was deployed into.') output resourceGroupName string = resourceGroup().name diff --git a/avm/res/health-bot/health-bot/main.json b/avm/res/health-bot/health-bot/main.json index 6f8d59ab81..acc6bacc25 100644 --- a/avm/res/health-bot/health-bot/main.json +++ b/avm/res/health-bot/health-bot/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "13278518763850368052" + "version": "0.26.54.24096", + "templateHash": "13957265537042927127" }, "name": "Azure Health Bots", "description": "This module deploys an Azure Health Bot.", diff --git a/avm/res/health-bot/health-bot/tests/e2e/defaults/main.test.bicep b/avm/res/health-bot/health-bot/tests/e2e/defaults/main.test.bicep index 8b458aca57..767ab4af97 100644 --- a/avm/res/health-bot/health-bot/tests/e2e/defaults/main.test.bicep +++ b/avm/res/health-bot/health-bot/tests/e2e/defaults/main.test.bicep @@ -36,12 +36,14 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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}002' - location: resourceGroup.location - sku: 'F0' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + location: resourceGroup.location + sku: 'F0' + } } -}] +] diff --git a/avm/res/health-bot/health-bot/tests/e2e/max/dependencies.bicep b/avm/res/health-bot/health-bot/tests/e2e/max/dependencies.bicep index 539240be2b..ad4e2ec09a 100644 --- a/avm/res/health-bot/health-bot/tests/e2e/max/dependencies.bicep +++ b/avm/res/health-bot/health-bot/tests/e2e/max/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The resource ID of the created Managed Identity.') diff --git a/avm/res/health-bot/health-bot/tests/e2e/max/main.test.bicep b/avm/res/health-bot/health-bot/tests/e2e/max/main.test.bicep index 173d84268b..bb00e40d5f 100644 --- a/avm/res/health-bot/health-bot/tests/e2e/max/main.test.bicep +++ b/avm/res/health-bot/health-bot/tests/e2e/max/main.test.bicep @@ -45,46 +45,51 @@ 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}002' - location: resourceGroup.location - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + location: resourceGroup.location + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + sku: 'F0' + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - sku: 'F0' - managedIdentities: { - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep b/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep index ca8e64a199..f559c16801 100644 --- a/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep @@ -36,21 +36,23 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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}002' - location: resourceGroup.location - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + location: resourceGroup.location + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + sku: 'F0' } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - sku: 'F0' } -}] +] diff --git a/avm/res/insights/action-group/main.bicep b/avm/res/insights/action-group/main.bicep index 8f4dfc69e5..89ad05f0ba 100644 --- a/avm/res/insights/action-group/main.bicep +++ b/avm/res/insights/action-group/main.bicep @@ -57,27 +57,34 @@ 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.insights-actiongroup.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.insights-actiongroup.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource actionGroup 'Microsoft.Insights/actionGroups@2023-01-01' = { name: name @@ -99,19 +106,25 @@ resource actionGroup 'Microsoft.Insights/actionGroups@2023-01-01' = { } } -resource actionGroup_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(actionGroup.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource actionGroup_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(actionGroup.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: actionGroup } - scope: actionGroup -}] +] @description('The resource group the action group was deployed into.') output resourceGroupName string = resourceGroup().name diff --git a/avm/res/insights/action-group/main.json b/avm/res/insights/action-group/main.json index db92f1556e..baa6e6af1e 100644 --- a/avm/res/insights/action-group/main.json +++ b/avm/res/insights/action-group/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "452819506402297284" + "version": "0.26.54.24096", + "templateHash": "3572364605280930173" }, "name": "Action Groups", "description": "This module deploys an Action Group.", diff --git a/avm/res/insights/action-group/tests/e2e/defaults/main.test.bicep b/avm/res/insights/action-group/tests/e2e/defaults/main.test.bicep index 6091b16997..9f0d06aa1f 100644 --- a/avm/res/insights/action-group/tests/e2e/defaults/main.test.bicep +++ b/avm/res/insights/action-group/tests/e2e/defaults/main.test.bicep @@ -36,12 +36,14 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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: 'global' - groupShortName: 'ag${serviceShort}001' +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: 'global' + groupShortName: 'ag${serviceShort}001' + } } -}] +] diff --git a/avm/res/insights/action-group/tests/e2e/max/dependencies.bicep b/avm/res/insights/action-group/tests/e2e/max/dependencies.bicep index a7f42aee7b..7be39e253a 100644 --- a/avm/res/insights/action-group/tests/e2e/max/dependencies.bicep +++ b/avm/res/insights/action-group/tests/e2e/max/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/insights/action-group/tests/e2e/max/main.test.bicep b/avm/res/insights/action-group/tests/e2e/max/main.test.bicep index a11a34591d..3a06f69507 100644 --- a/avm/res/insights/action-group/tests/e2e/max/main.test.bicep +++ b/avm/res/insights/action-group/tests/e2e/max/main.test.bicep @@ -45,53 +45,58 @@ 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: 'global' - groupShortName: 'ag${serviceShort}001' - emailReceivers: [ - { - emailAddress: 'test.user@testcompany.com' - name: 'TestUser_-EmailAction-' - useCommonAlertSchema: true - } - { - emailAddress: 'test.user2@testcompany.com' - name: 'TestUser2' - useCommonAlertSchema: true - } - ] - 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' - } - ] - smsReceivers: [ - { - countryCode: '1' - name: 'TestUser_-SMSAction-' - phoneNumber: '2345678901' +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: 'global' + groupShortName: 'ag${serviceShort}001' + emailReceivers: [ + { + emailAddress: 'test.user@testcompany.com' + name: 'TestUser_-EmailAction-' + useCommonAlertSchema: true + } + { + emailAddress: 'test.user2@testcompany.com' + name: 'TestUser2' + useCommonAlertSchema: true + } + ] + 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' + } + ] + smsReceivers: [ + { + countryCode: '1' + name: 'TestUser_-SMSAction-' + phoneNumber: '2345678901' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/insights/action-group/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/insights/action-group/tests/e2e/waf-aligned/dependencies.bicep index a7f42aee7b..7be39e253a 100644 --- a/avm/res/insights/action-group/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/insights/action-group/tests/e2e/waf-aligned/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/insights/action-group/tests/e2e/waf-aligned/main.test.bicep b/avm/res/insights/action-group/tests/e2e/waf-aligned/main.test.bicep index 68492a4ecb..e2195df6ee 100644 --- a/avm/res/insights/action-group/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/insights/action-group/tests/e2e/waf-aligned/main.test.bicep @@ -45,17 +45,19 @@ 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: 'global' - groupShortName: 'ag${serviceShort}001' - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +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: 'global' + groupShortName: 'ag${serviceShort}001' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } } -}] +] diff --git a/avm/res/insights/activity-log-alert/main.bicep b/avm/res/insights/activity-log-alert/main.bicep index 231f56fca7..559309346a 100644 --- a/avm/res/insights/activity-log-alert/main.bicep +++ b/avm/res/insights/activity-log-alert/main.bicep @@ -34,36 +34,45 @@ param tags object? @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -var actionGroups = [for action in actions: { - actionGroupId: contains(action, 'actionGroupId') ? action.actionGroupId : action - webhookProperties: contains(action, 'webhookProperties') ? action.webhookProperties : null -}] +var actionGroups = [ + for action in actions: { + actionGroupId: contains(action, 'actionGroupId') ? action.actionGroupId : action + webhookProperties: contains(action, 'webhookProperties') ? action.webhookProperties : 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.insights-activitylogalert.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.insights-activitylogalert.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource activityLogAlert 'Microsoft.Insights/activityLogAlerts@2020-10-01' = { name: name @@ -82,19 +91,25 @@ resource activityLogAlert 'Microsoft.Insights/activityLogAlerts@2020-10-01' = { } } -resource activityLogAlert_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(activityLogAlert.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource activityLogAlert_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(activityLogAlert.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: activityLogAlert } - scope: activityLogAlert -}] +] @description('The name of the activity log alert.') output name string = activityLogAlert.name diff --git a/avm/res/insights/activity-log-alert/main.json b/avm/res/insights/activity-log-alert/main.json index 567c3f6c42..e7904d72d1 100644 --- a/avm/res/insights/activity-log-alert/main.json +++ b/avm/res/insights/activity-log-alert/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11885081769153040344" + "version": "0.26.54.24096", + "templateHash": "4555927328226234726" }, "name": "Activity Log Alerts", "description": "This module deploys an Activity Log Alert.", diff --git a/avm/res/insights/activity-log-alert/tests/e2e/defaults/main.test.bicep b/avm/res/insights/activity-log-alert/tests/e2e/defaults/main.test.bicep index 3de3c2af28..5b099760e2 100644 --- a/avm/res/insights/activity-log-alert/tests/e2e/defaults/main.test.bicep +++ b/avm/res/insights/activity-log-alert/tests/e2e/defaults/main.test.bicep @@ -36,41 +36,43 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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: 'global' - conditions: [ - { - field: 'category' - equals: 'ServiceHealth' - } - { - anyOf: [ - { - field: 'properties.incidentType' - equals: 'Incident' - } - { - field: 'properties.incidentType' - equals: 'Maintenance' - } - ] - } - { - field: 'properties.impactedServices[*].ServiceName' - containsAny: [ - 'Storage' - ] - } - { - field: 'properties.impactedServices[*].ImpactedRegions[*].RegionName' - containsAny: [ - 'West Europe' - ] - } - ] +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: 'global' + conditions: [ + { + field: 'category' + equals: 'ServiceHealth' + } + { + anyOf: [ + { + field: 'properties.incidentType' + equals: 'Incident' + } + { + field: 'properties.incidentType' + equals: 'Maintenance' + } + ] + } + { + field: 'properties.impactedServices[*].ServiceName' + containsAny: [ + 'Storage' + ] + } + { + field: 'properties.impactedServices[*].ImpactedRegions[*].RegionName' + containsAny: [ + 'West Europe' + ] + } + ] + } } -}] +] diff --git a/avm/res/insights/activity-log-alert/tests/e2e/max/main.test.bicep b/avm/res/insights/activity-log-alert/tests/e2e/max/main.test.bicep index 796fb3756e..dd3bb2c84b 100644 --- a/avm/res/insights/activity-log-alert/tests/e2e/max/main.test.bicep +++ b/avm/res/insights/activity-log-alert/tests/e2e/max/main.test.bicep @@ -46,73 +46,78 @@ 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: 'global' - conditions: [ - { - field: 'category' - equals: 'ServiceHealth' - } - { - anyOf: [ - { - field: 'properties.incidentType' - equals: 'Incident' - } - { - field: 'properties.incidentType' - equals: 'Maintenance' - } - ] - } - { - field: 'properties.impactedServices[*].ServiceName' - containsAny: [ - 'Action Groups' - 'Activity Logs & Alerts' - ] - } - { - field: 'properties.impactedServices[*].ImpactedRegions[*].RegionName' - containsAny: [ - 'West Europe' - 'Global' - ] - } - ] - actions: [ - { - actionGroupId: nestedDependencies.outputs.actionGroupResourceId - } - ] - 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' +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: 'global' + conditions: [ + { + field: 'category' + equals: 'ServiceHealth' + } + { + anyOf: [ + { + field: 'properties.incidentType' + equals: 'Incident' + } + { + field: 'properties.incidentType' + equals: 'Maintenance' + } + ] + } + { + field: 'properties.impactedServices[*].ServiceName' + containsAny: [ + 'Action Groups' + 'Activity Logs & Alerts' + ] + } + { + field: 'properties.impactedServices[*].ImpactedRegions[*].RegionName' + containsAny: [ + 'West Europe' + 'Global' + ] + } + ] + actions: [ + { + actionGroupId: nestedDependencies.outputs.actionGroupResourceId + } + ] + 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' + } + ] + scopes: [ + subscription().id + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - scopes: [ - subscription().id - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/insights/activity-log-alert/tests/e2e/waf-aligned/main.test.bicep b/avm/res/insights/activity-log-alert/tests/e2e/waf-aligned/main.test.bicep index 7af69a877b..e86926d0b7 100644 --- a/avm/res/insights/activity-log-alert/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/insights/activity-log-alert/tests/e2e/waf-aligned/main.test.bicep @@ -44,56 +44,58 @@ 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: 'global' - conditions: [ - { - field: 'category' - equals: 'ServiceHealth' - } - { - anyOf: [ - { - field: 'properties.incidentType' - equals: 'Incident' - } - { - field: 'properties.incidentType' - equals: 'Maintenance' - } - ] - } - { - field: 'properties.impactedServices[*].ServiceName' - containsAny: [ - 'Action Groups' - 'Activity Logs & Alerts' - ] - } - { - field: 'properties.impactedServices[*].ImpactedRegions[*].RegionName' - containsAny: [ - 'West Europe' - 'Global' - ] - } - ] - actions: [ - { - actionGroupId: nestedDependencies.outputs.actionGroupResourceId +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: 'global' + conditions: [ + { + field: 'category' + equals: 'ServiceHealth' + } + { + anyOf: [ + { + field: 'properties.incidentType' + equals: 'Incident' + } + { + field: 'properties.incidentType' + equals: 'Maintenance' + } + ] + } + { + field: 'properties.impactedServices[*].ServiceName' + containsAny: [ + 'Action Groups' + 'Activity Logs & Alerts' + ] + } + { + field: 'properties.impactedServices[*].ImpactedRegions[*].RegionName' + containsAny: [ + 'West Europe' + 'Global' + ] + } + ] + actions: [ + { + actionGroupId: nestedDependencies.outputs.actionGroupResourceId + } + ] + scopes: [ + subscription().id + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - scopes: [ - subscription().id - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/insights/component/linkedStorageAccounts/main.json b/avm/res/insights/component/linkedStorageAccounts/main.json index 853cdbcf3a..13b7ff86e1 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.25.53.49325", - "templateHash": "15515506165880058222" + "version": "0.26.54.24096", + "templateHash": "10843790724446601865" }, "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 26504d0676..fe78cec221 100644 --- a/avm/res/insights/component/main.bicep +++ b/avm/res/insights/component/main.bicep @@ -82,27 +82,34 @@ 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.insights-component.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.insights-component.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource appInsights 'Microsoft.Insights/components@2020-02-02' = { name: name @@ -122,50 +129,63 @@ resource appInsights 'Microsoft.Insights/components@2020-02-02' = { } } -module linkedStorageAccount 'linkedStorageAccounts/main.bicep' = if (!empty(linkedStorageAccountResourceId)) { - name: '${uniqueString(deployment().name, location)}-appInsights-linkedStorageAccount' - params: { - appInsightsName: appInsights.name - storageAccountResourceId: linkedStorageAccountResourceId +module linkedStorageAccount 'linkedStorageAccounts/main.bicep' = + if (!empty(linkedStorageAccountResourceId)) { + name: '${uniqueString(deployment().name, location)}-appInsights-linkedStorageAccount' + params: { + appInsightsName: appInsights.name + storageAccountResourceId: linkedStorageAccountResourceId + } } -} -resource appInsights_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(appInsights.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource appInsights_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(appInsights.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: appInsights } - scope: appInsights -}] - -resource appInsights_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +] + +resource appInsights_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: appInsights } - scope: appInsights -}] +] @description('The name of the application insights component.') output name string = appInsights.name diff --git a/avm/res/insights/component/main.json b/avm/res/insights/component/main.json index a479a84010..2cfb14e258 100644 --- a/avm/res/insights/component/main.json +++ b/avm/res/insights/component/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2927135998555920691" + "version": "0.26.54.24096", + "templateHash": "6536051249599059447" }, "name": "Application Insights", "description": "This component deploys an Application Insights instance.", @@ -478,8 +478,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "15515506165880058222" + "version": "0.26.54.24096", + "templateHash": "10843790724446601865" }, "name": "Application Insights Linked Storage Account", "description": "This component deploys an Application Insights Linked Storage Account.", diff --git a/avm/res/insights/component/tests/e2e/defaults/dependencies.bicep b/avm/res/insights/component/tests/e2e/defaults/dependencies.bicep index cc24476629..63e7a207db 100644 --- a/avm/res/insights/component/tests/e2e/defaults/dependencies.bicep +++ b/avm/res/insights/component/tests/e2e/defaults/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param logAnalyticsWorkspaceName string resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' = { - name: logAnalyticsWorkspaceName - location: location + name: logAnalyticsWorkspaceName + location: location } @description('The resource ID of the created Log Analytics Workspace.') diff --git a/avm/res/insights/component/tests/e2e/max/main.test.bicep b/avm/res/insights/component/tests/e2e/max/main.test.bicep index 1f587dd740..899534b33a 100644 --- a/avm/res/insights/component/tests/e2e/max/main.test.bicep +++ b/avm/res/insights/component/tests/e2e/max/main.test.bicep @@ -96,7 +96,10 @@ module testDeployment '../../../main.bicep' = { principalType: 'ServicePrincipal' } { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) principalId: nestedDependencies.outputs.managedIdentityPrincipalId principalType: 'ServicePrincipal' } diff --git a/avm/res/insights/component/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/insights/component/tests/e2e/waf-aligned/dependencies.bicep index a7f42aee7b..7be39e253a 100644 --- a/avm/res/insights/component/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/insights/component/tests/e2e/waf-aligned/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/insights/data-collection-endpoint/main.bicep b/avm/res/insights/data-collection-endpoint/main.bicep index cffa96ea8c..7e8ca0fbab 100644 --- a/avm/res/insights/data-collection-endpoint/main.bicep +++ b/avm/res/insights/data-collection-endpoint/main.bicep @@ -42,31 +42,38 @@ 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } // =============== // // Deployments // // =============== // -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.insights-datacollectionendpoint.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.insights-datacollectionendpoint.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource dataCollectionEndpoint 'Microsoft.Insights/dataCollectionEndpoints@2021-04-01' = { kind: kind @@ -80,28 +87,37 @@ resource dataCollectionEndpoint 'Microsoft.Insights/dataCollectionEndpoints@2021 } } -resource dataCollectionEndpoint_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.' +resource dataCollectionEndpoint_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: dataCollectionEndpoint } - scope: dataCollectionEndpoint -} -resource dataCollectionEndpoint_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(dataCollectionEndpoint.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource dataCollectionEndpoint_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(dataCollectionEndpoint.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: dataCollectionEndpoint } - scope: dataCollectionEndpoint -}] +] // =========== // // Outputs // diff --git a/avm/res/insights/data-collection-endpoint/main.json b/avm/res/insights/data-collection-endpoint/main.json index 01c4550922..acdabe202e 100644 --- a/avm/res/insights/data-collection-endpoint/main.json +++ b/avm/res/insights/data-collection-endpoint/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2640603462631612916" + "version": "0.26.54.24096", + "templateHash": "3365574102168324158" }, "name": "Data Collection Endpoints", "description": "This module deploys a Data Collection Endpoint.", diff --git a/avm/res/insights/data-collection-endpoint/tests/e2e/defaults/main.test.bicep b/avm/res/insights/data-collection-endpoint/tests/e2e/defaults/main.test.bicep index 88c90cd91c..cdf5ac6d3a 100644 --- a/avm/res/insights/data-collection-endpoint/tests/e2e/defaults/main.test.bicep +++ b/avm/res/insights/data-collection-endpoint/tests/e2e/defaults/main.test.bicep @@ -35,11 +35,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 +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 + } } -}] +] diff --git a/avm/res/insights/data-collection-endpoint/tests/e2e/max/main.test.bicep b/avm/res/insights/data-collection-endpoint/tests/e2e/max/main.test.bicep index f1247259b2..2089ac4f21 100644 --- a/avm/res/insights/data-collection-endpoint/tests/e2e/max/main.test.bicep +++ b/avm/res/insights/data-collection-endpoint/tests/e2e/max/main.test.bicep @@ -44,39 +44,44 @@ 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 - publicNetworkAccess: 'Enabled' - kind: 'Windows' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +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 + publicNetworkAccess: 'Enabled' + kind: 'Windows' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + resourceType: 'Data Collection Rules' + kind: 'Windows' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - resourceType: 'Data Collection Rules' - kind: 'Windows' } } -}] +] diff --git a/avm/res/insights/data-collection-endpoint/tests/e2e/waf-aligned/main.test.bicep b/avm/res/insights/data-collection-endpoint/tests/e2e/waf-aligned/main.test.bicep index 4766a05468..e421f1282a 100644 --- a/avm/res/insights/data-collection-endpoint/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/insights/data-collection-endpoint/tests/e2e/waf-aligned/main.test.bicep @@ -35,18 +35,20 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 - publicNetworkAccess: 'Disabled' - kind: 'Windows' - tags: { - 'hidden-title': 'This is visible in the resource name' - resourceType: 'Data Collection Rules' +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 + publicNetworkAccess: 'Disabled' kind: 'Windows' + tags: { + 'hidden-title': 'This is visible in the resource name' + resourceType: 'Data Collection Rules' + kind: 'Windows' + } } } -}] +] diff --git a/avm/res/insights/data-collection-rule/main.bicep b/avm/res/insights/data-collection-rule/main.bicep index 1195de6abd..a7dacba601 100644 --- a/avm/res/insights/data-collection-rule/main.bicep +++ b/avm/res/insights/data-collection-rule/main.bicep @@ -57,27 +57,34 @@ 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.insights-datacollectionrule.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.insights-datacollectionrule.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource dataCollectionRule 'Microsoft.Insights/dataCollectionRules@2021-09-01-preview' = { kind: kind @@ -94,28 +101,37 @@ resource dataCollectionRule 'Microsoft.Insights/dataCollectionRules@2021-09-01-p } } -resource dataCollectionRule_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.' +resource dataCollectionRule_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: dataCollectionRule } - scope: dataCollectionRule -} -resource dataCollectionRule_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(dataCollectionRule.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource dataCollectionRule_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(dataCollectionRule.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: dataCollectionRule } - scope: dataCollectionRule -}] +] // =========== // // Outputs // diff --git a/avm/res/insights/data-collection-rule/main.json b/avm/res/insights/data-collection-rule/main.json index b076b6e1de..e029f11464 100644 --- a/avm/res/insights/data-collection-rule/main.json +++ b/avm/res/insights/data-collection-rule/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11839102114188195603" + "version": "0.26.54.24096", + "templateHash": "7431041910788264170" }, "name": "Data Collection Rules", "description": "This module deploys a Data Collection Rule.", diff --git a/avm/res/insights/data-collection-rule/tests/e2e/customadv/dependencies.bicep b/avm/res/insights/data-collection-rule/tests/e2e/customadv/dependencies.bicep index dc07e5f605..35ea4ba120 100644 --- a/avm/res/insights/data-collection-rule/tests/e2e/customadv/dependencies.bicep +++ b/avm/res/insights/data-collection-rule/tests/e2e/customadv/dependencies.bicep @@ -8,54 +8,54 @@ param dataCollectionEndpointName string param logAnalyticsWorkspaceName string resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = { - name: logAnalyticsWorkspaceName - location: location + name: logAnalyticsWorkspaceName + location: location - resource customTableAdvanced 'tables@2022-10-01' = { + resource customTableAdvanced 'tables@2022-10-01' = { + name: 'CustomTableAdvanced_CL' + properties: { + schema: { name: 'CustomTableAdvanced_CL' - properties: { - schema: { - name: 'CustomTableAdvanced_CL' - columns: [ - { - name: 'TimeGenerated' - type: 'DateTime' - } - { - name: 'EventTime' - type: 'DateTime' - } - { - name: 'EventLevel' - type: 'String' - } - { - name: 'EventCode' - type: 'Int' - } - { - name: 'Message' - type: 'String' - } - { - name: 'RawData' - type: 'String' - } - ] - } - } + columns: [ + { + name: 'TimeGenerated' + type: 'DateTime' + } + { + name: 'EventTime' + type: 'DateTime' + } + { + name: 'EventLevel' + type: 'String' + } + { + name: 'EventCode' + type: 'Int' + } + { + name: 'Message' + type: 'String' + } + { + name: 'RawData' + type: 'String' + } + ] + } } + } } resource dataCollectionEndpoint 'Microsoft.Insights/dataCollectionEndpoints@2021-04-01' = { - kind: 'Windows' - location: location - name: dataCollectionEndpointName - properties: { - networkAcls: { - publicNetworkAccess: 'Enabled' - } + kind: 'Windows' + location: location + name: dataCollectionEndpointName + properties: { + networkAcls: { + publicNetworkAccess: 'Enabled' } + } } @description('The resource ID of the created Log Analytics Workspace.') diff --git a/avm/res/insights/data-collection-rule/tests/e2e/customadv/main.test.bicep b/avm/res/insights/data-collection-rule/tests/e2e/customadv/main.test.bicep index ded0c6e219..6eb2366a0b 100644 --- a/avm/res/insights/data-collection-rule/tests/e2e/customadv/main.test.bicep +++ b/avm/res/insights/data-collection-rule/tests/e2e/customadv/main.test.bicep @@ -45,89 +45,91 @@ 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 - dataCollectionEndpointId: nestedDependencies.outputs.dataCollectionEndpointResourceId - description: 'Collecting custom text logs with ingestion-time transformation to columns. Expected format of a log line (comma separated values): ",,,", for example: "2023-01-25T20:15:05Z,ERROR,404,Page not found"' - dataFlows: [ - { - streams: [ - 'Custom-CustomTableAdvanced_CL' - ] - destinations: [ - nestedDependencies.outputs.logAnalyticsWorkspaceName - ] - transformKql: 'source | extend LogFields = split(RawData, ",") | extend EventTime = todatetime(LogFields[0]) | extend EventLevel = tostring(LogFields[1]) | extend EventCode = toint(LogFields[2]) | extend Message = tostring(LogFields[3]) | project TimeGenerated, EventTime, EventLevel, EventCode, Message' - outputStream: 'Custom-CustomTableAdvanced_CL' - } - ] - dataSources: { - logFiles: [ +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 + dataCollectionEndpointId: nestedDependencies.outputs.dataCollectionEndpointResourceId + description: 'Collecting custom text logs with ingestion-time transformation to columns. Expected format of a log line (comma separated values): ",,,", for example: "2023-01-25T20:15:05Z,ERROR,404,Page not found"' + dataFlows: [ { - name: 'CustomTableAdvanced_CL' - samplingFrequencyInSeconds: 60 streams: [ 'Custom-CustomTableAdvanced_CL' ] - filePatterns: [ - 'C:\\TestLogsAdvanced\\TestLog*.log' + destinations: [ + nestedDependencies.outputs.logAnalyticsWorkspaceName ] - format: 'text' - settings: { - text: { - recordStartTimestampFormat: 'ISO 8601' - } - } - } - ] - } - destinations: { - logAnalytics: [ - { - workspaceResourceId: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId - name: nestedDependencies.outputs.logAnalyticsWorkspaceName + transformKql: 'source | extend LogFields = split(RawData, ",") | extend EventTime = todatetime(LogFields[0]) | extend EventLevel = tostring(LogFields[1]) | extend EventCode = toint(LogFields[2]) | extend Message = tostring(LogFields[3]) | project TimeGenerated, EventTime, EventLevel, EventCode, Message' + outputStream: 'Custom-CustomTableAdvanced_CL' } ] - } - streamDeclarations: { - 'Custom-CustomTableAdvanced_CL': { - columns: [ + dataSources: { + logFiles: [ { - name: 'TimeGenerated' - type: 'datetime' - } - { - name: 'EventTime' - type: 'datetime' - } - { - name: 'EventLevel' - type: 'string' - } - { - name: 'EventCode' - type: 'int' - } - { - name: 'Message' - type: 'string' + name: 'CustomTableAdvanced_CL' + samplingFrequencyInSeconds: 60 + streams: [ + 'Custom-CustomTableAdvanced_CL' + ] + filePatterns: [ + 'C:\\TestLogsAdvanced\\TestLog*.log' + ] + format: 'text' + settings: { + text: { + recordStartTimestampFormat: 'ISO 8601' + } + } } + ] + } + destinations: { + logAnalytics: [ { - name: 'RawData' - type: 'string' + workspaceResourceId: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId + name: nestedDependencies.outputs.logAnalyticsWorkspaceName } ] } - } - kind: 'Windows' - tags: { - 'hidden-title': 'This is visible in the resource name' - resourceType: 'Data Collection Rules' + streamDeclarations: { + 'Custom-CustomTableAdvanced_CL': { + columns: [ + { + name: 'TimeGenerated' + type: 'datetime' + } + { + name: 'EventTime' + type: 'datetime' + } + { + name: 'EventLevel' + type: 'string' + } + { + name: 'EventCode' + type: 'int' + } + { + name: 'Message' + type: 'string' + } + { + name: 'RawData' + type: 'string' + } + ] + } + } kind: 'Windows' + tags: { + 'hidden-title': 'This is visible in the resource name' + resourceType: 'Data Collection Rules' + kind: 'Windows' + } } } -}] +] diff --git a/avm/res/insights/data-collection-rule/tests/e2e/custombasic/dependencies.bicep b/avm/res/insights/data-collection-rule/tests/e2e/custombasic/dependencies.bicep index 4afb136cb6..0412e61164 100644 --- a/avm/res/insights/data-collection-rule/tests/e2e/custombasic/dependencies.bicep +++ b/avm/res/insights/data-collection-rule/tests/e2e/custombasic/dependencies.bicep @@ -8,38 +8,38 @@ param dataCollectionEndpointName string param logAnalyticsWorkspaceName string resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = { - name: logAnalyticsWorkspaceName - location: location + name: logAnalyticsWorkspaceName + location: location - resource customTableBasic 'tables@2022-10-01' = { + resource customTableBasic 'tables@2022-10-01' = { + name: 'CustomTableBasic_CL' + properties: { + schema: { name: 'CustomTableBasic_CL' - properties: { - schema: { - name: 'CustomTableBasic_CL' - columns: [ - { - name: 'TimeGenerated' - type: 'DateTime' - } - { - name: 'RawData' - type: 'String' - } - ] - } - } + columns: [ + { + name: 'TimeGenerated' + type: 'DateTime' + } + { + name: 'RawData' + type: 'String' + } + ] + } } + } } resource dataCollectionEndpoint 'Microsoft.Insights/dataCollectionEndpoints@2021-04-01' = { - kind: 'Windows' - location: location - name: dataCollectionEndpointName - properties: { - networkAcls: { - publicNetworkAccess: 'Enabled' - } + kind: 'Windows' + location: location + name: dataCollectionEndpointName + properties: { + networkAcls: { + publicNetworkAccess: 'Enabled' } + } } @description('The resource ID of the created Log Analytics Workspace.') diff --git a/avm/res/insights/data-collection-rule/tests/e2e/custombasic/main.test.bicep b/avm/res/insights/data-collection-rule/tests/e2e/custombasic/main.test.bicep index 3fa5aac564..cf1e2a9b3c 100644 --- a/avm/res/insights/data-collection-rule/tests/e2e/custombasic/main.test.bicep +++ b/avm/res/insights/data-collection-rule/tests/e2e/custombasic/main.test.bicep @@ -45,73 +45,75 @@ 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 - dataCollectionEndpointId: nestedDependencies.outputs.dataCollectionEndpointResourceId - description: 'Collecting custom text logs without ingestion-time transformation.' - dataFlows: [ - { - streams: [ - 'Custom-CustomTableBasic_CL' - ] - destinations: [ - nestedDependencies.outputs.logAnalyticsWorkspaceName - ] - transformKql: 'source' - outputStream: 'Custom-CustomTableBasic_CL' - } - ] - dataSources: { - logFiles: [ +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 + dataCollectionEndpointId: nestedDependencies.outputs.dataCollectionEndpointResourceId + description: 'Collecting custom text logs without ingestion-time transformation.' + dataFlows: [ { - name: 'CustomTableBasic_CL' - samplingFrequencyInSeconds: 60 streams: [ 'Custom-CustomTableBasic_CL' ] - filePatterns: [ - 'C:\\TestLogsBasic\\TestLog*.log' + destinations: [ + nestedDependencies.outputs.logAnalyticsWorkspaceName ] - format: 'text' - settings: { - text: { - recordStartTimestampFormat: 'ISO 8601' - } - } - } - ] - } - destinations: { - logAnalytics: [ - { - workspaceResourceId: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId - name: nestedDependencies.outputs.logAnalyticsWorkspaceName + transformKql: 'source' + outputStream: 'Custom-CustomTableBasic_CL' } ] - } - streamDeclarations: { - 'Custom-CustomTableBasic_CL': { - columns: [ + dataSources: { + logFiles: [ { - name: 'TimeGenerated' - type: 'datetime' + name: 'CustomTableBasic_CL' + samplingFrequencyInSeconds: 60 + streams: [ + 'Custom-CustomTableBasic_CL' + ] + filePatterns: [ + 'C:\\TestLogsBasic\\TestLog*.log' + ] + format: 'text' + settings: { + text: { + recordStartTimestampFormat: 'ISO 8601' + } + } } + ] + } + destinations: { + logAnalytics: [ { - name: 'RawData' - type: 'string' + workspaceResourceId: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId + name: nestedDependencies.outputs.logAnalyticsWorkspaceName } ] } - } - kind: 'Windows' - tags: { - 'hidden-title': 'This is visible in the resource name' - resourceType: 'Data Collection Rules' + streamDeclarations: { + 'Custom-CustomTableBasic_CL': { + columns: [ + { + name: 'TimeGenerated' + type: 'datetime' + } + { + name: 'RawData' + type: 'string' + } + ] + } + } kind: 'Windows' + tags: { + 'hidden-title': 'This is visible in the resource name' + resourceType: 'Data Collection Rules' + kind: 'Windows' + } } } -}] +] diff --git a/avm/res/insights/data-collection-rule/tests/e2e/customiis/dependencies.bicep b/avm/res/insights/data-collection-rule/tests/e2e/customiis/dependencies.bicep index 0a3bc96cfe..b12b662cc7 100644 --- a/avm/res/insights/data-collection-rule/tests/e2e/customiis/dependencies.bicep +++ b/avm/res/insights/data-collection-rule/tests/e2e/customiis/dependencies.bicep @@ -8,19 +8,19 @@ param dataCollectionEndpointName string param logAnalyticsWorkspaceName string resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = { - name: logAnalyticsWorkspaceName - location: location + name: logAnalyticsWorkspaceName + location: location } resource dataCollectionEndpoint 'Microsoft.Insights/dataCollectionEndpoints@2021-04-01' = { - kind: 'Windows' - location: location - name: dataCollectionEndpointName - properties: { - networkAcls: { - publicNetworkAccess: 'Enabled' - } + kind: 'Windows' + location: location + name: dataCollectionEndpointName + properties: { + networkAcls: { + publicNetworkAccess: 'Enabled' } + } } @description('The resource ID of the created Log Analytics Workspace.') diff --git a/avm/res/insights/data-collection-rule/tests/e2e/customiis/main.test.bicep b/avm/res/insights/data-collection-rule/tests/e2e/customiis/main.test.bicep index 4c8af81827..fa08fbf64c 100644 --- a/avm/res/insights/data-collection-rule/tests/e2e/customiis/main.test.bicep +++ b/avm/res/insights/data-collection-rule/tests/e2e/customiis/main.test.bicep @@ -45,52 +45,54 @@ 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 - dataCollectionEndpointId: nestedDependencies.outputs.dataCollectionEndpointResourceId - description: 'Collecting IIS logs.' - dataFlows: [ - { - streams: [ - 'Microsoft-W3CIISLog' - ] - destinations: [ - nestedDependencies.outputs.logAnalyticsWorkspaceName - ] - transformKql: 'source' - outputStream: 'Microsoft-W3CIISLog' - } - ] - dataSources: { - iisLogs: [ +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 + dataCollectionEndpointId: nestedDependencies.outputs.dataCollectionEndpointResourceId + description: 'Collecting IIS logs.' + dataFlows: [ { - name: 'iisLogsDataSource' streams: [ 'Microsoft-W3CIISLog' ] - logDirectories: [ - 'C:\\inetpub\\logs\\LogFiles\\W3SVC1' + destinations: [ + nestedDependencies.outputs.logAnalyticsWorkspaceName ] + transformKql: 'source' + outputStream: 'Microsoft-W3CIISLog' } ] - } - destinations: { - logAnalytics: [ - { - workspaceResourceId: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId - name: nestedDependencies.outputs.logAnalyticsWorkspaceName - } - ] - } - kind: 'Windows' - tags: { - 'hidden-title': 'This is visible in the resource name' - resourceType: 'Data Collection Rules' + dataSources: { + iisLogs: [ + { + name: 'iisLogsDataSource' + streams: [ + 'Microsoft-W3CIISLog' + ] + logDirectories: [ + 'C:\\inetpub\\logs\\LogFiles\\W3SVC1' + ] + } + ] + } + destinations: { + logAnalytics: [ + { + workspaceResourceId: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId + name: nestedDependencies.outputs.logAnalyticsWorkspaceName + } + ] + } kind: 'Windows' + tags: { + 'hidden-title': 'This is visible in the resource name' + resourceType: 'Data Collection Rules' + kind: 'Windows' + } } } -}] +] diff --git a/avm/res/insights/data-collection-rule/tests/e2e/defaults/main.test.bicep b/avm/res/insights/data-collection-rule/tests/e2e/defaults/main.test.bicep index fc46e9ec99..8a9070c88e 100644 --- a/avm/res/insights/data-collection-rule/tests/e2e/defaults/main.test.bicep +++ b/avm/res/insights/data-collection-rule/tests/e2e/defaults/main.test.bicep @@ -35,50 +35,52 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 - dataSources: { - performanceCounters: [ +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 + dataSources: { + performanceCounters: [ + { + name: 'perfCounterDataSource60' + samplingFrequencyInSeconds: 60 + streams: [ + 'Microsoft-InsightsMetrics' + ] + counterSpecifiers: [ + '\\Processor Information(_Total)\\% Processor Time' + '\\Processor Information(_Total)\\% Privileged Time' + '\\Processor Information(_Total)\\% User Time' + '\\Processor Information(_Total)\\Processor Frequency' + '\\System\\Processes' + '\\Process(_Total)\\Thread Count' + '\\Process(_Total)\\Handle Count' + '\\System\\System Up Time' + '\\System\\Context Switches/sec' + '\\System\\Processor Queue Length' + ] + } + ] + } + destinations: { + azureMonitorMetrics: { + name: 'azureMonitorMetrics-default' + } + } + dataFlows: [ { - name: 'perfCounterDataSource60' - samplingFrequencyInSeconds: 60 streams: [ 'Microsoft-InsightsMetrics' ] - counterSpecifiers: [ - '\\Processor Information(_Total)\\% Processor Time' - '\\Processor Information(_Total)\\% Privileged Time' - '\\Processor Information(_Total)\\% User Time' - '\\Processor Information(_Total)\\Processor Frequency' - '\\System\\Processes' - '\\Process(_Total)\\Thread Count' - '\\Process(_Total)\\Handle Count' - '\\System\\System Up Time' - '\\System\\Context Switches/sec' - '\\System\\Processor Queue Length' + destinations: [ + 'azureMonitorMetrics-default' ] } ] + kind: 'Windows' } - destinations: { - azureMonitorMetrics: { - name: 'azureMonitorMetrics-default' - } - } - dataFlows: [ - { - streams: [ - 'Microsoft-InsightsMetrics' - ] - destinations: [ - 'azureMonitorMetrics-default' - ] - } - ] - kind: 'Windows' } -}] +] diff --git a/avm/res/insights/data-collection-rule/tests/e2e/linux/dependencies.bicep b/avm/res/insights/data-collection-rule/tests/e2e/linux/dependencies.bicep index 7d1119142f..c20b584c10 100644 --- a/avm/res/insights/data-collection-rule/tests/e2e/linux/dependencies.bicep +++ b/avm/res/insights/data-collection-rule/tests/e2e/linux/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param logAnalyticsWorkspaceName string resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = { - name: logAnalyticsWorkspaceName - location: location + name: logAnalyticsWorkspaceName + location: location } @description('The resource ID of the created Log Analytics Workspace.') diff --git a/avm/res/insights/data-collection-rule/tests/e2e/linux/main.test.bicep b/avm/res/insights/data-collection-rule/tests/e2e/linux/main.test.bicep index 8f8435b569..7ffc209efb 100644 --- a/avm/res/insights/data-collection-rule/tests/e2e/linux/main.test.bicep +++ b/avm/res/insights/data-collection-rule/tests/e2e/linux/main.test.bicep @@ -44,166 +44,167 @@ 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 - description: 'Collecting Linux-specific performance counters and Linux Syslog' - dataSources: { - performanceCounters: [ - { - name: 'perfCounterDataSource60' - samplingFrequencyInSeconds: 60 - streams: [ - 'Microsoft-InsightsMetrics' - ] - counterSpecifiers: [ - 'Processor(*)\\% Processor Time' - 'Processor(*)\\% Idle Time' - 'Processor(*)\\% User Time' - 'Processor(*)\\% Nice Time' - 'Processor(*)\\% Privileged Time' - 'Processor(*)\\% IO Wait Time' - 'Processor(*)\\% Interrupt Time' - 'Processor(*)\\% DPC Time' - 'Memory(*)\\Available MBytes Memory' - 'Memory(*)\\% Available Memory' - 'Memory(*)\\Used Memory MBytes' - 'Memory(*)\\% Used Memory' - 'Memory(*)\\Pages/sec' - 'Memory(*)\\Page Reads/sec' - 'Memory(*)\\Page Writes/sec' - 'Memory(*)\\Available MBytes Swap' - 'Memory(*)\\% Available Swap Space' - 'Memory(*)\\Used MBytes Swap Space' - 'Memory(*)\\% Used Swap Space' - 'Logical Disk(*)\\% Free Inodes' - 'Logical Disk(*)\\% Used Inodes' - 'Logical Disk(*)\\Free Megabytes' - 'Logical Disk(*)\\% Free Space' - 'Logical Disk(*)\\% Used Space' - 'Logical Disk(*)\\Logical Disk Bytes/sec' - 'Logical Disk(*)\\Disk Read Bytes/sec' - 'Logical Disk(*)\\Disk Write Bytes/sec' - 'Logical Disk(*)\\Disk Transfers/sec' - 'Logical Disk(*)\\Disk Reads/sec' - 'Logical Disk(*)\\Disk Writes/sec' - 'Network(*)\\Total Bytes Transmitted' - 'Network(*)\\Total Bytes Received' - 'Network(*)\\Total Bytes' - 'Network(*)\\Total Packets Transmitted' - 'Network(*)\\Total Packets Received' - 'Network(*)\\Total Rx Errors' - 'Network(*)\\Total Tx Errors' - 'Network(*)\\Total Collisions' - ] - } - ] - syslog: [ - { - name: 'sysLogsDataSource-debugLevel' - streams: [ - 'Microsoft-Syslog' - ] - facilityNames: [ - 'auth' - 'authpriv' - ] - logLevels: [ - 'Debug' - 'Info' - 'Notice' - 'Warning' - 'Error' - 'Critical' - 'Alert' - 'Emergency' - ] +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 + description: 'Collecting Linux-specific performance counters and Linux Syslog' + dataSources: { + performanceCounters: [ + { + name: 'perfCounterDataSource60' + samplingFrequencyInSeconds: 60 + streams: [ + 'Microsoft-InsightsMetrics' + ] + counterSpecifiers: [ + 'Processor(*)\\% Processor Time' + 'Processor(*)\\% Idle Time' + 'Processor(*)\\% User Time' + 'Processor(*)\\% Nice Time' + 'Processor(*)\\% Privileged Time' + 'Processor(*)\\% IO Wait Time' + 'Processor(*)\\% Interrupt Time' + 'Processor(*)\\% DPC Time' + 'Memory(*)\\Available MBytes Memory' + 'Memory(*)\\% Available Memory' + 'Memory(*)\\Used Memory MBytes' + 'Memory(*)\\% Used Memory' + 'Memory(*)\\Pages/sec' + 'Memory(*)\\Page Reads/sec' + 'Memory(*)\\Page Writes/sec' + 'Memory(*)\\Available MBytes Swap' + 'Memory(*)\\% Available Swap Space' + 'Memory(*)\\Used MBytes Swap Space' + 'Memory(*)\\% Used Swap Space' + 'Logical Disk(*)\\% Free Inodes' + 'Logical Disk(*)\\% Used Inodes' + 'Logical Disk(*)\\Free Megabytes' + 'Logical Disk(*)\\% Free Space' + 'Logical Disk(*)\\% Used Space' + 'Logical Disk(*)\\Logical Disk Bytes/sec' + 'Logical Disk(*)\\Disk Read Bytes/sec' + 'Logical Disk(*)\\Disk Write Bytes/sec' + 'Logical Disk(*)\\Disk Transfers/sec' + 'Logical Disk(*)\\Disk Reads/sec' + 'Logical Disk(*)\\Disk Writes/sec' + 'Network(*)\\Total Bytes Transmitted' + 'Network(*)\\Total Bytes Received' + 'Network(*)\\Total Bytes' + 'Network(*)\\Total Packets Transmitted' + 'Network(*)\\Total Packets Received' + 'Network(*)\\Total Rx Errors' + 'Network(*)\\Total Tx Errors' + 'Network(*)\\Total Collisions' + ] + } + ] + syslog: [ + { + name: 'sysLogsDataSource-debugLevel' + streams: [ + 'Microsoft-Syslog' + ] + facilityNames: [ + 'auth' + 'authpriv' + ] + logLevels: [ + 'Debug' + 'Info' + 'Notice' + 'Warning' + 'Error' + 'Critical' + 'Alert' + 'Emergency' + ] + } + { + name: 'sysLogsDataSource-warningLevel' + streams: [ + 'Microsoft-Syslog' + ] + facilityNames: [ + 'cron' + 'daemon' + 'mark' + 'kern' + 'local0' + ] + logLevels: [ + 'Warning' + 'Error' + 'Critical' + 'Alert' + 'Emergency' + ] + } + { + name: 'sysLogsDataSource-errLevel' + streams: [ + 'Microsoft-Syslog' + ] + facilityNames: [ + 'local1' + 'local2' + 'local3' + 'local4' + 'local5' + 'local6' + 'local7' + 'lpr' + 'mail' + 'news' + 'syslog' + ] + logLevels: [ + 'Error' + 'Critical' + 'Alert' + 'Emergency' + ] + } + ] + } + destinations: { + azureMonitorMetrics: { + name: 'azureMonitorMetrics-default' } + logAnalytics: [ + { + workspaceResourceId: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId + name: nestedDependencies.outputs.logAnalyticsWorkspaceName + } + ] + } + dataFlows: [ { - name: 'sysLogsDataSource-warningLevel' streams: [ - 'Microsoft-Syslog' - ] - facilityNames: [ - 'cron' - 'daemon' - 'mark' - 'kern' - 'local0' + 'Microsoft-InsightsMetrics' ] - logLevels: [ - 'Warning' - 'Error' - 'Critical' - 'Alert' - 'Emergency' + destinations: [ + 'azureMonitorMetrics-default' ] } { - name: 'sysLogsDataSource-errLevel' streams: [ 'Microsoft-Syslog' ] - facilityNames: [ - 'local1' - 'local2' - 'local3' - 'local4' - 'local5' - 'local6' - 'local7' - 'lpr' - 'mail' - 'news' - 'syslog' - ] - logLevels: [ - 'Error' - 'Critical' - 'Alert' - 'Emergency' + destinations: [ + nestedDependencies.outputs.logAnalyticsWorkspaceName ] } ] - } - destinations: { - azureMonitorMetrics: { - name: 'azureMonitorMetrics-default' - } - logAnalytics: [ - { - workspaceResourceId: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId - name: nestedDependencies.outputs.logAnalyticsWorkspaceName - } - ] - } - dataFlows: [ - { - streams: [ - 'Microsoft-InsightsMetrics' - ] - destinations: [ - 'azureMonitorMetrics-default' - ] - } - { - streams: [ - 'Microsoft-Syslog' - ] - destinations: [ - nestedDependencies.outputs.logAnalyticsWorkspaceName - ] - } - - ] - kind: 'Linux' - tags: { - 'hidden-title': 'This is visible in the resource name' - resourceType: 'Data Collection Rules' kind: 'Linux' + tags: { + 'hidden-title': 'This is visible in the resource name' + resourceType: 'Data Collection Rules' + kind: 'Linux' + } } } -}] +] diff --git a/avm/res/insights/data-collection-rule/tests/e2e/max/dependencies.bicep b/avm/res/insights/data-collection-rule/tests/e2e/max/dependencies.bicep index f1804cde92..e7a3cd006b 100644 --- a/avm/res/insights/data-collection-rule/tests/e2e/max/dependencies.bicep +++ b/avm/res/insights/data-collection-rule/tests/e2e/max/dependencies.bicep @@ -11,43 +11,43 @@ param logAnalyticsWorkspaceName string param managedIdentityName string resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = { - name: logAnalyticsWorkspaceName - location: location + name: logAnalyticsWorkspaceName + location: location - resource customTableBasic 'tables@2022-10-01' = { + resource customTableBasic 'tables@2022-10-01' = { + name: 'CustomTableBasic_CL' + properties: { + schema: { name: 'CustomTableBasic_CL' - properties: { - schema: { - name: 'CustomTableBasic_CL' - columns: [ - { - name: 'TimeGenerated' - type: 'DateTime' - } - { - name: 'RawData' - type: 'String' - } - ] - } - } + columns: [ + { + name: 'TimeGenerated' + type: 'DateTime' + } + { + name: 'RawData' + type: 'String' + } + ] + } } + } } resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } resource dataCollectionEndpoint 'Microsoft.Insights/dataCollectionEndpoints@2021-04-01' = { - kind: 'Windows' - location: location - name: dataCollectionEndpointName - properties: { - networkAcls: { - publicNetworkAccess: 'Enabled' - } + kind: 'Windows' + location: location + name: dataCollectionEndpointName + properties: { + networkAcls: { + publicNetworkAccess: 'Enabled' } + } } @description('The resource ID of the created Log Analytics Workspace.') diff --git a/avm/res/insights/data-collection-rule/tests/e2e/max/main.test.bicep b/avm/res/insights/data-collection-rule/tests/e2e/max/main.test.bicep index 7bafac2eb6..cf81a64bfc 100644 --- a/avm/res/insights/data-collection-rule/tests/e2e/max/main.test.bicep +++ b/avm/res/insights/data-collection-rule/tests/e2e/max/main.test.bicep @@ -46,94 +46,99 @@ 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 - dataCollectionEndpointId: nestedDependencies.outputs.dataCollectionEndpointResourceId - description: 'Collecting custom text logs without ingestion-time transformation.' - dataFlows: [ - { - streams: [ - 'Custom-CustomTableBasic_CL' - ] - destinations: [ - nestedDependencies.outputs.logAnalyticsWorkspaceName - ] - transformKql: 'source' - outputStream: 'Custom-CustomTableBasic_CL' - } - ] - dataSources: { - logFiles: [ +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 + dataCollectionEndpointId: nestedDependencies.outputs.dataCollectionEndpointResourceId + description: 'Collecting custom text logs without ingestion-time transformation.' + dataFlows: [ { - name: 'CustomTableBasic_CL' - samplingFrequencyInSeconds: 60 streams: [ 'Custom-CustomTableBasic_CL' ] - filePatterns: [ - 'C:\\TestLogsBasic\\TestLog*.log' + destinations: [ + nestedDependencies.outputs.logAnalyticsWorkspaceName ] - format: 'text' - settings: { - text: { - recordStartTimestampFormat: 'ISO 8601' - } - } + transformKql: 'source' + outputStream: 'Custom-CustomTableBasic_CL' } ] - } - destinations: { - logAnalytics: [ - { - workspaceResourceId: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId - name: nestedDependencies.outputs.logAnalyticsWorkspaceName - } - ] - } - streamDeclarations: { - 'Custom-CustomTableBasic_CL': { - columns: [ + dataSources: { + logFiles: [ { - name: 'TimeGenerated' - type: 'datetime' + name: 'CustomTableBasic_CL' + samplingFrequencyInSeconds: 60 + streams: [ + 'Custom-CustomTableBasic_CL' + ] + filePatterns: [ + 'C:\\TestLogsBasic\\TestLog*.log' + ] + format: 'text' + settings: { + text: { + recordStartTimestampFormat: 'ISO 8601' + } + } } + ] + } + destinations: { + logAnalytics: [ { - name: 'RawData' - type: 'string' + workspaceResourceId: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId + name: nestedDependencies.outputs.logAnalyticsWorkspaceName } ] } - } - kind: 'Windows' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + streamDeclarations: { + 'Custom-CustomTableBasic_CL': { + columns: [ + { + name: 'TimeGenerated' + type: 'datetime' + } + { + name: 'RawData' + type: 'string' + } + ] + } } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + kind: 'Windows' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + resourceType: 'Data Collection Rules' + kind: 'Windows' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - resourceType: 'Data Collection Rules' - kind: 'Windows' } } -}] +] diff --git a/avm/res/insights/data-collection-rule/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/insights/data-collection-rule/tests/e2e/waf-aligned/dependencies.bicep index 7d1119142f..c20b584c10 100644 --- a/avm/res/insights/data-collection-rule/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/insights/data-collection-rule/tests/e2e/waf-aligned/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param logAnalyticsWorkspaceName string resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = { - name: logAnalyticsWorkspaceName - location: location + name: logAnalyticsWorkspaceName + location: location } @description('The resource ID of the created Log Analytics Workspace.') diff --git a/avm/res/insights/data-collection-rule/tests/e2e/waf-aligned/main.test.bicep b/avm/res/insights/data-collection-rule/tests/e2e/waf-aligned/main.test.bicep index 7c566cc632..c1b93f95b5 100644 --- a/avm/res/insights/data-collection-rule/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/insights/data-collection-rule/tests/e2e/waf-aligned/main.test.bicep @@ -45,120 +45,121 @@ 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 - description: 'Collecting Windows-specific performance counters and Windows Event Logs' - dataSources: { - performanceCounters: [ +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 + description: 'Collecting Windows-specific performance counters and Windows Event Logs' + dataSources: { + performanceCounters: [ + { + name: 'perfCounterDataSource60' + samplingFrequencyInSeconds: 60 + streams: [ + 'Microsoft-InsightsMetrics' + ] + counterSpecifiers: [ + '\\Processor Information(_Total)\\% Processor Time' + '\\Processor Information(_Total)\\% Privileged Time' + '\\Processor Information(_Total)\\% User Time' + '\\Processor Information(_Total)\\Processor Frequency' + '\\System\\Processes' + '\\Process(_Total)\\Thread Count' + '\\Process(_Total)\\Handle Count' + '\\System\\System Up Time' + '\\System\\Context Switches/sec' + '\\System\\Processor Queue Length' + '\\Memory\\% Committed Bytes In Use' + '\\Memory\\Available Bytes' + '\\Memory\\Committed Bytes' + '\\Memory\\Cache Bytes' + '\\Memory\\Pool Paged Bytes' + '\\Memory\\Pool Nonpaged Bytes' + '\\Memory\\Pages/sec' + '\\Memory\\Page Faults/sec' + '\\Process(_Total)\\Working Set' + '\\Process(_Total)\\Working Set - Private' + '\\LogicalDisk(_Total)\\% Disk Time' + '\\LogicalDisk(_Total)\\% Disk Read Time' + '\\LogicalDisk(_Total)\\% Disk Write Time' + '\\LogicalDisk(_Total)\\% Idle Time' + '\\LogicalDisk(_Total)\\Disk Bytes/sec' + '\\LogicalDisk(_Total)\\Disk Read Bytes/sec' + '\\LogicalDisk(_Total)\\Disk Write Bytes/sec' + '\\LogicalDisk(_Total)\\Disk Transfers/sec' + '\\LogicalDisk(_Total)\\Disk Reads/sec' + '\\LogicalDisk(_Total)\\Disk Writes/sec' + '\\LogicalDisk(_Total)\\Avg. Disk sec/Transfer' + '\\LogicalDisk(_Total)\\Avg. Disk sec/Read' + '\\LogicalDisk(_Total)\\Avg. Disk sec/Write' + '\\LogicalDisk(_Total)\\Avg. Disk Queue Length' + '\\LogicalDisk(_Total)\\Avg. Disk Read Queue Length' + '\\LogicalDisk(_Total)\\Avg. Disk Write Queue Length' + '\\LogicalDisk(_Total)\\% Free Space' + '\\LogicalDisk(_Total)\\Free Megabytes' + '\\Network Interface(*)\\Bytes Total/sec' + '\\Network Interface(*)\\Bytes Sent/sec' + '\\Network Interface(*)\\Bytes Received/sec' + '\\Network Interface(*)\\Packets/sec' + '\\Network Interface(*)\\Packets Sent/sec' + '\\Network Interface(*)\\Packets Received/sec' + '\\Network Interface(*)\\Packets Outbound Errors' + '\\Network Interface(*)\\Packets Received Errors' + ] + } + ] + windowsEventLogs: [ + { + name: 'eventLogsDataSource' + streams: [ + 'Microsoft-Event' + ] + xPathQueries: [ + 'Application!*[System[(Level=1 or Level=2 or Level=3 or Level=4 or Level=0 or Level=5)]]' + 'Security!*[System[(band(Keywords,13510798882111488))]]' + 'System!*[System[(Level=1 or Level=2 or Level=3 or Level=4 or Level=0 or Level=5)]]' + ] + } + ] + } + destinations: { + azureMonitorMetrics: { + name: 'azureMonitorMetrics-default' + } + logAnalytics: [ + { + workspaceResourceId: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId + name: nestedDependencies.outputs.logAnalyticsWorkspaceName + } + ] + } + dataFlows: [ { - name: 'perfCounterDataSource60' - samplingFrequencyInSeconds: 60 streams: [ 'Microsoft-InsightsMetrics' ] - counterSpecifiers: [ - '\\Processor Information(_Total)\\% Processor Time' - '\\Processor Information(_Total)\\% Privileged Time' - '\\Processor Information(_Total)\\% User Time' - '\\Processor Information(_Total)\\Processor Frequency' - '\\System\\Processes' - '\\Process(_Total)\\Thread Count' - '\\Process(_Total)\\Handle Count' - '\\System\\System Up Time' - '\\System\\Context Switches/sec' - '\\System\\Processor Queue Length' - '\\Memory\\% Committed Bytes In Use' - '\\Memory\\Available Bytes' - '\\Memory\\Committed Bytes' - '\\Memory\\Cache Bytes' - '\\Memory\\Pool Paged Bytes' - '\\Memory\\Pool Nonpaged Bytes' - '\\Memory\\Pages/sec' - '\\Memory\\Page Faults/sec' - '\\Process(_Total)\\Working Set' - '\\Process(_Total)\\Working Set - Private' - '\\LogicalDisk(_Total)\\% Disk Time' - '\\LogicalDisk(_Total)\\% Disk Read Time' - '\\LogicalDisk(_Total)\\% Disk Write Time' - '\\LogicalDisk(_Total)\\% Idle Time' - '\\LogicalDisk(_Total)\\Disk Bytes/sec' - '\\LogicalDisk(_Total)\\Disk Read Bytes/sec' - '\\LogicalDisk(_Total)\\Disk Write Bytes/sec' - '\\LogicalDisk(_Total)\\Disk Transfers/sec' - '\\LogicalDisk(_Total)\\Disk Reads/sec' - '\\LogicalDisk(_Total)\\Disk Writes/sec' - '\\LogicalDisk(_Total)\\Avg. Disk sec/Transfer' - '\\LogicalDisk(_Total)\\Avg. Disk sec/Read' - '\\LogicalDisk(_Total)\\Avg. Disk sec/Write' - '\\LogicalDisk(_Total)\\Avg. Disk Queue Length' - '\\LogicalDisk(_Total)\\Avg. Disk Read Queue Length' - '\\LogicalDisk(_Total)\\Avg. Disk Write Queue Length' - '\\LogicalDisk(_Total)\\% Free Space' - '\\LogicalDisk(_Total)\\Free Megabytes' - '\\Network Interface(*)\\Bytes Total/sec' - '\\Network Interface(*)\\Bytes Sent/sec' - '\\Network Interface(*)\\Bytes Received/sec' - '\\Network Interface(*)\\Packets/sec' - '\\Network Interface(*)\\Packets Sent/sec' - '\\Network Interface(*)\\Packets Received/sec' - '\\Network Interface(*)\\Packets Outbound Errors' - '\\Network Interface(*)\\Packets Received Errors' + destinations: [ + 'azureMonitorMetrics-default' ] } - ] - windowsEventLogs: [ { - name: 'eventLogsDataSource' streams: [ 'Microsoft-Event' ] - xPathQueries: [ - 'Application!*[System[(Level=1 or Level=2 or Level=3 or Level=4 or Level=0 or Level=5)]]' - 'Security!*[System[(band(Keywords,13510798882111488))]]' - 'System!*[System[(Level=1 or Level=2 or Level=3 or Level=4 or Level=0 or Level=5)]]' + destinations: [ + nestedDependencies.outputs.logAnalyticsWorkspaceName ] } ] - } - destinations: { - azureMonitorMetrics: { - name: 'azureMonitorMetrics-default' - } - logAnalytics: [ - { - workspaceResourceId: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId - name: nestedDependencies.outputs.logAnalyticsWorkspaceName - } - ] - } - dataFlows: [ - { - streams: [ - 'Microsoft-InsightsMetrics' - ] - destinations: [ - 'azureMonitorMetrics-default' - ] - } - { - streams: [ - 'Microsoft-Event' - ] - destinations: [ - nestedDependencies.outputs.logAnalyticsWorkspaceName - ] - } - - ] - kind: 'Windows' - tags: { - 'hidden-title': 'This is visible in the resource name' - resourceType: 'Data Collection Rules' kind: 'Windows' + tags: { + 'hidden-title': 'This is visible in the resource name' + resourceType: 'Data Collection Rules' + kind: 'Windows' + } } } -}] +] diff --git a/avm/res/insights/data-collection-rule/tests/e2e/windows/dependencies.bicep b/avm/res/insights/data-collection-rule/tests/e2e/windows/dependencies.bicep index 7d1119142f..c20b584c10 100644 --- a/avm/res/insights/data-collection-rule/tests/e2e/windows/dependencies.bicep +++ b/avm/res/insights/data-collection-rule/tests/e2e/windows/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param logAnalyticsWorkspaceName string resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = { - name: logAnalyticsWorkspaceName - location: location + name: logAnalyticsWorkspaceName + location: location } @description('The resource ID of the created Log Analytics Workspace.') diff --git a/avm/res/insights/data-collection-rule/tests/e2e/windows/main.test.bicep b/avm/res/insights/data-collection-rule/tests/e2e/windows/main.test.bicep index 9bc58edc58..d5e29bfc40 100644 --- a/avm/res/insights/data-collection-rule/tests/e2e/windows/main.test.bicep +++ b/avm/res/insights/data-collection-rule/tests/e2e/windows/main.test.bicep @@ -44,120 +44,121 @@ 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 - description: 'Collecting Windows-specific performance counters and Windows Event Logs' - dataSources: { - performanceCounters: [ +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 + description: 'Collecting Windows-specific performance counters and Windows Event Logs' + dataSources: { + performanceCounters: [ + { + name: 'perfCounterDataSource60' + samplingFrequencyInSeconds: 60 + streams: [ + 'Microsoft-InsightsMetrics' + ] + counterSpecifiers: [ + '\\Processor Information(_Total)\\% Processor Time' + '\\Processor Information(_Total)\\% Privileged Time' + '\\Processor Information(_Total)\\% User Time' + '\\Processor Information(_Total)\\Processor Frequency' + '\\System\\Processes' + '\\Process(_Total)\\Thread Count' + '\\Process(_Total)\\Handle Count' + '\\System\\System Up Time' + '\\System\\Context Switches/sec' + '\\System\\Processor Queue Length' + '\\Memory\\% Committed Bytes In Use' + '\\Memory\\Available Bytes' + '\\Memory\\Committed Bytes' + '\\Memory\\Cache Bytes' + '\\Memory\\Pool Paged Bytes' + '\\Memory\\Pool Nonpaged Bytes' + '\\Memory\\Pages/sec' + '\\Memory\\Page Faults/sec' + '\\Process(_Total)\\Working Set' + '\\Process(_Total)\\Working Set - Private' + '\\LogicalDisk(_Total)\\% Disk Time' + '\\LogicalDisk(_Total)\\% Disk Read Time' + '\\LogicalDisk(_Total)\\% Disk Write Time' + '\\LogicalDisk(_Total)\\% Idle Time' + '\\LogicalDisk(_Total)\\Disk Bytes/sec' + '\\LogicalDisk(_Total)\\Disk Read Bytes/sec' + '\\LogicalDisk(_Total)\\Disk Write Bytes/sec' + '\\LogicalDisk(_Total)\\Disk Transfers/sec' + '\\LogicalDisk(_Total)\\Disk Reads/sec' + '\\LogicalDisk(_Total)\\Disk Writes/sec' + '\\LogicalDisk(_Total)\\Avg. Disk sec/Transfer' + '\\LogicalDisk(_Total)\\Avg. Disk sec/Read' + '\\LogicalDisk(_Total)\\Avg. Disk sec/Write' + '\\LogicalDisk(_Total)\\Avg. Disk Queue Length' + '\\LogicalDisk(_Total)\\Avg. Disk Read Queue Length' + '\\LogicalDisk(_Total)\\Avg. Disk Write Queue Length' + '\\LogicalDisk(_Total)\\% Free Space' + '\\LogicalDisk(_Total)\\Free Megabytes' + '\\Network Interface(*)\\Bytes Total/sec' + '\\Network Interface(*)\\Bytes Sent/sec' + '\\Network Interface(*)\\Bytes Received/sec' + '\\Network Interface(*)\\Packets/sec' + '\\Network Interface(*)\\Packets Sent/sec' + '\\Network Interface(*)\\Packets Received/sec' + '\\Network Interface(*)\\Packets Outbound Errors' + '\\Network Interface(*)\\Packets Received Errors' + ] + } + ] + windowsEventLogs: [ + { + name: 'eventLogsDataSource' + streams: [ + 'Microsoft-Event' + ] + xPathQueries: [ + 'Application!*[System[(Level=1 or Level=2 or Level=3 or Level=4 or Level=0 or Level=5)]]' + 'Security!*[System[(band(Keywords,13510798882111488))]]' + 'System!*[System[(Level=1 or Level=2 or Level=3 or Level=4 or Level=0 or Level=5)]]' + ] + } + ] + } + destinations: { + azureMonitorMetrics: { + name: 'azureMonitorMetrics-default' + } + logAnalytics: [ + { + workspaceResourceId: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId + name: nestedDependencies.outputs.logAnalyticsWorkspaceName + } + ] + } + dataFlows: [ { - name: 'perfCounterDataSource60' - samplingFrequencyInSeconds: 60 streams: [ 'Microsoft-InsightsMetrics' ] - counterSpecifiers: [ - '\\Processor Information(_Total)\\% Processor Time' - '\\Processor Information(_Total)\\% Privileged Time' - '\\Processor Information(_Total)\\% User Time' - '\\Processor Information(_Total)\\Processor Frequency' - '\\System\\Processes' - '\\Process(_Total)\\Thread Count' - '\\Process(_Total)\\Handle Count' - '\\System\\System Up Time' - '\\System\\Context Switches/sec' - '\\System\\Processor Queue Length' - '\\Memory\\% Committed Bytes In Use' - '\\Memory\\Available Bytes' - '\\Memory\\Committed Bytes' - '\\Memory\\Cache Bytes' - '\\Memory\\Pool Paged Bytes' - '\\Memory\\Pool Nonpaged Bytes' - '\\Memory\\Pages/sec' - '\\Memory\\Page Faults/sec' - '\\Process(_Total)\\Working Set' - '\\Process(_Total)\\Working Set - Private' - '\\LogicalDisk(_Total)\\% Disk Time' - '\\LogicalDisk(_Total)\\% Disk Read Time' - '\\LogicalDisk(_Total)\\% Disk Write Time' - '\\LogicalDisk(_Total)\\% Idle Time' - '\\LogicalDisk(_Total)\\Disk Bytes/sec' - '\\LogicalDisk(_Total)\\Disk Read Bytes/sec' - '\\LogicalDisk(_Total)\\Disk Write Bytes/sec' - '\\LogicalDisk(_Total)\\Disk Transfers/sec' - '\\LogicalDisk(_Total)\\Disk Reads/sec' - '\\LogicalDisk(_Total)\\Disk Writes/sec' - '\\LogicalDisk(_Total)\\Avg. Disk sec/Transfer' - '\\LogicalDisk(_Total)\\Avg. Disk sec/Read' - '\\LogicalDisk(_Total)\\Avg. Disk sec/Write' - '\\LogicalDisk(_Total)\\Avg. Disk Queue Length' - '\\LogicalDisk(_Total)\\Avg. Disk Read Queue Length' - '\\LogicalDisk(_Total)\\Avg. Disk Write Queue Length' - '\\LogicalDisk(_Total)\\% Free Space' - '\\LogicalDisk(_Total)\\Free Megabytes' - '\\Network Interface(*)\\Bytes Total/sec' - '\\Network Interface(*)\\Bytes Sent/sec' - '\\Network Interface(*)\\Bytes Received/sec' - '\\Network Interface(*)\\Packets/sec' - '\\Network Interface(*)\\Packets Sent/sec' - '\\Network Interface(*)\\Packets Received/sec' - '\\Network Interface(*)\\Packets Outbound Errors' - '\\Network Interface(*)\\Packets Received Errors' + destinations: [ + 'azureMonitorMetrics-default' ] } - ] - windowsEventLogs: [ { - name: 'eventLogsDataSource' streams: [ 'Microsoft-Event' ] - xPathQueries: [ - 'Application!*[System[(Level=1 or Level=2 or Level=3 or Level=4 or Level=0 or Level=5)]]' - 'Security!*[System[(band(Keywords,13510798882111488))]]' - 'System!*[System[(Level=1 or Level=2 or Level=3 or Level=4 or Level=0 or Level=5)]]' + destinations: [ + nestedDependencies.outputs.logAnalyticsWorkspaceName ] } ] - } - destinations: { - azureMonitorMetrics: { - name: 'azureMonitorMetrics-default' - } - logAnalytics: [ - { - workspaceResourceId: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId - name: nestedDependencies.outputs.logAnalyticsWorkspaceName - } - ] - } - dataFlows: [ - { - streams: [ - 'Microsoft-InsightsMetrics' - ] - destinations: [ - 'azureMonitorMetrics-default' - ] - } - { - streams: [ - 'Microsoft-Event' - ] - destinations: [ - nestedDependencies.outputs.logAnalyticsWorkspaceName - ] - } - - ] - kind: 'Windows' - tags: { - 'hidden-title': 'This is visible in the resource name' - resourceType: 'Data Collection Rules' kind: 'Windows' + tags: { + 'hidden-title': 'This is visible in the resource name' + resourceType: 'Data Collection Rules' + kind: 'Windows' + } } } -}] +] diff --git a/avm/res/insights/diagnostic-setting/main.bicep b/avm/res/insights/diagnostic-setting/main.bicep index c55623e60c..9f5a177338 100644 --- a/avm/res/insights/diagnostic-setting/main.bicep +++ b/avm/res/insights/diagnostic-setting/main.bicep @@ -44,24 +44,25 @@ param enableTelemetry bool = true @description('Optional. Location deployment metadata.') param location string = deployment().location -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.insights-diagnosticsetting.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - location: location - 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' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.insights-diagnosticsetting.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + location: location + 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' + } } } } } -} resource diagnosticSetting 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { name: name @@ -72,16 +73,20 @@ resource diagnosticSetting 'Microsoft.Insights/diagnosticSettings@2021-05-01-pre eventHubName: eventHubName logAnalyticsDestinationType: !empty(logAnalyticsDestinationType) ? logAnalyticsDestinationType : null marketplacePartnerId: marketplacePartnerResourceId - logs: [for group in (logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - metrics: [for group in (metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] + logs: [ + for group in (logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + metrics: [ + for group in (metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] } } diff --git a/avm/res/insights/diagnostic-setting/main.json b/avm/res/insights/diagnostic-setting/main.json index abbf525d82..158031e200 100644 --- a/avm/res/insights/diagnostic-setting/main.json +++ b/avm/res/insights/diagnostic-setting/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "5117333214781202133" + "version": "0.26.54.24096", + "templateHash": "5981394739767783762" }, "name": "Diagnostic Settings (Activity Logs) for Azure Subscriptions", "description": "This module deploys a Subscription wide export of the Activity Log.", diff --git a/avm/res/insights/diagnostic-setting/tests/e2e/defaults/main.test.bicep b/avm/res/insights/diagnostic-setting/tests/e2e/defaults/main.test.bicep index 324cb36d18..41cd930d47 100644 --- a/avm/res/insights/diagnostic-setting/tests/e2e/defaults/main.test.bicep +++ b/avm/res/insights/diagnostic-setting/tests/e2e/defaults/main.test.bicep @@ -50,11 +50,13 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - name: '${namePrefix}${serviceShort}001' - location: resourceLocation - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: resourceLocation + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } } -}] +] diff --git a/avm/res/insights/diagnostic-setting/tests/e2e/max/main.test.bicep b/avm/res/insights/diagnostic-setting/tests/e2e/max/main.test.bicep index 08aea32676..a8c6832848 100644 --- a/avm/res/insights/diagnostic-setting/tests/e2e/max/main.test.bicep +++ b/avm/res/insights/diagnostic-setting/tests/e2e/max/main.test.bicep @@ -50,19 +50,21 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - name: '${namePrefix}${serviceShort}001' - location: resourceLocation - 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']: { + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: resourceLocation + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } } -}] +] diff --git a/avm/res/insights/diagnostic-setting/tests/e2e/waf-aligned/main.test.bicep b/avm/res/insights/diagnostic-setting/tests/e2e/waf-aligned/main.test.bicep index 02a93b9eb2..eec20b3471 100644 --- a/avm/res/insights/diagnostic-setting/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/insights/diagnostic-setting/tests/e2e/waf-aligned/main.test.bicep @@ -50,19 +50,21 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - name: '${namePrefix}${serviceShort}001' - location: resourceLocation - 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']: { + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: resourceLocation + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } } -}] +] diff --git a/avm/res/insights/metric-alert/main.bicep b/avm/res/insights/metric-alert/main.bicep index 04650703e9..9bd5b95162 100644 --- a/avm/res/insights/metric-alert/main.bicep +++ b/avm/res/insights/metric-alert/main.bicep @@ -84,36 +84,45 @@ param tags object? @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -var actionGroups = [for action in actions: { - actionGroupId: contains(action, 'actionGroupId') ? action.actionGroupId : action - webHookProperties: contains(action, 'webHookProperties') ? action.webHookProperties : null -}] +var actionGroups = [ + for action in actions: { + actionGroupId: contains(action, 'actionGroupId') ? action.actionGroupId : action + webHookProperties: contains(action, 'webHookProperties') ? action.webHookProperties : 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.insights-metricalert.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.insights-metricalert.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource metricAlert 'Microsoft.Insights/metricAlerts@2018-03-01' = { name: name @@ -137,19 +146,25 @@ resource metricAlert 'Microsoft.Insights/metricAlerts@2018-03-01' = { } } -resource metricAlert_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(metricAlert.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource metricAlert_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(metricAlert.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: metricAlert } - scope: metricAlert -}] +] @description('The resource group the metric alert was deployed into.') output resourceGroupName string = resourceGroup().name diff --git a/avm/res/insights/metric-alert/main.json b/avm/res/insights/metric-alert/main.json index 2d3ca25563..c80ef0e731 100644 --- a/avm/res/insights/metric-alert/main.json +++ b/avm/res/insights/metric-alert/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3036524835571607907" + "version": "0.26.54.24096", + "templateHash": "7733798583122178659" }, "name": "Metric Alerts", "description": "This module deploys a Metric Alert.", diff --git a/avm/res/insights/metric-alert/tests/e2e/defaults/main.test.bicep b/avm/res/insights/metric-alert/tests/e2e/defaults/main.test.bicep index 1e5d69fa27..bf6a693cc3 100644 --- a/avm/res/insights/metric-alert/tests/e2e/defaults/main.test.bicep +++ b/avm/res/insights/metric-alert/tests/e2e/defaults/main.test.bicep @@ -36,24 +36,26 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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: 'Global' - criterias: [ - { - criterionType: 'StaticThresholdCriterion' - metricName: 'Percentage CPU' - metricNamespace: 'microsoft.compute/virtualmachines' - name: 'HighCPU' - operator: 'GreaterThan' - threshold: '90' - timeAggregation: 'Average' - } - ] - targetResourceRegion: 'westeurope' - targetResourceType: 'microsoft.compute/virtualmachines' +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: 'Global' + criterias: [ + { + criterionType: 'StaticThresholdCriterion' + metricName: 'Percentage CPU' + metricNamespace: 'microsoft.compute/virtualmachines' + name: 'HighCPU' + operator: 'GreaterThan' + threshold: '90' + timeAggregation: 'Average' + } + ] + targetResourceRegion: 'westeurope' + targetResourceType: 'microsoft.compute/virtualmachines' + } } -}] +] diff --git a/avm/res/insights/metric-alert/tests/e2e/max/dependencies.bicep b/avm/res/insights/metric-alert/tests/e2e/max/dependencies.bicep index eb23eca835..38c9636e26 100644 --- a/avm/res/insights/metric-alert/tests/e2e/max/dependencies.bicep +++ b/avm/res/insights/metric-alert/tests/e2e/max/dependencies.bicep @@ -8,18 +8,18 @@ param managedIdentityName string param actionGroupName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } resource actionGroup 'Microsoft.Insights/actionGroups@2022-06-01' = { - name: actionGroupName - location: 'global' + name: actionGroupName + location: 'global' - properties: { - enabled: true - groupShortName: substring(actionGroupName, 0, 11) - } + properties: { + enabled: true + groupShortName: substring(actionGroupName, 0, 11) + } } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/insights/metric-alert/tests/e2e/max/main.test.bicep b/avm/res/insights/metric-alert/tests/e2e/max/main.test.bicep index a6c15d2793..2d4de682aa 100644 --- a/avm/res/insights/metric-alert/tests/e2e/max/main.test.bicep +++ b/avm/res/insights/metric-alert/tests/e2e/max/main.test.bicep @@ -46,51 +46,56 @@ 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: 'Global' - criterias: [ - { - criterionType: 'StaticThresholdCriterion' - metricName: 'Percentage CPU' - metricNamespace: 'microsoft.compute/virtualmachines' - name: 'HighCPU' - operator: 'GreaterThan' - threshold: '90' - timeAggregation: 'Average' - } - ] - actions: [ - nestedDependencies.outputs.actionGroupResourceId - ] - alertCriteriaType: 'Microsoft.Azure.Monitor.MultipleResourceMultipleMetricCriteria' - 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' +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: 'Global' + criterias: [ + { + criterionType: 'StaticThresholdCriterion' + metricName: 'Percentage CPU' + metricNamespace: 'microsoft.compute/virtualmachines' + name: 'HighCPU' + operator: 'GreaterThan' + threshold: '90' + timeAggregation: 'Average' + } + ] + actions: [ + nestedDependencies.outputs.actionGroupResourceId + ] + alertCriteriaType: 'Microsoft.Azure.Monitor.MultipleResourceMultipleMetricCriteria' + 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' + } + ] + targetResourceRegion: 'westeurope' + targetResourceType: 'microsoft.compute/virtualmachines' + windowSize: 'PT15M' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - targetResourceRegion: 'westeurope' - targetResourceType: 'microsoft.compute/virtualmachines' - windowSize: 'PT15M' - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/insights/metric-alert/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/insights/metric-alert/tests/e2e/waf-aligned/dependencies.bicep index 68a384092c..b332d7fdc1 100644 --- a/avm/res/insights/metric-alert/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/insights/metric-alert/tests/e2e/waf-aligned/dependencies.bicep @@ -2,13 +2,13 @@ param actionGroupName string resource actionGroup 'Microsoft.Insights/actionGroups@2022-06-01' = { - name: actionGroupName - location: 'global' + name: actionGroupName + location: 'global' - properties: { - enabled: true - groupShortName: substring(actionGroupName, 0, 11) - } + properties: { + enabled: true + groupShortName: substring(actionGroupName, 0, 11) + } } @description('The resource ID of the created Action Group.') diff --git a/avm/res/insights/metric-alert/tests/e2e/waf-aligned/main.test.bicep b/avm/res/insights/metric-alert/tests/e2e/waf-aligned/main.test.bicep index e12bab9638..3c6db678cb 100644 --- a/avm/res/insights/metric-alert/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/insights/metric-alert/tests/e2e/waf-aligned/main.test.bicep @@ -44,34 +44,36 @@ 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: 'Global' - criterias: [ - { - criterionType: 'StaticThresholdCriterion' - metricName: 'Percentage CPU' - metricNamespace: 'microsoft.compute/virtualmachines' - name: 'HighCPU' - operator: 'GreaterThan' - threshold: '90' - timeAggregation: 'Average' +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: 'Global' + criterias: [ + { + criterionType: 'StaticThresholdCriterion' + metricName: 'Percentage CPU' + metricNamespace: 'microsoft.compute/virtualmachines' + name: 'HighCPU' + operator: 'GreaterThan' + threshold: '90' + timeAggregation: 'Average' + } + ] + actions: [ + nestedDependencies.outputs.actionGroupResourceId + ] + alertCriteriaType: 'Microsoft.Azure.Monitor.MultipleResourceMultipleMetricCriteria' + targetResourceRegion: 'westeurope' + targetResourceType: 'microsoft.compute/virtualmachines' + windowSize: 'PT15M' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - actions: [ - nestedDependencies.outputs.actionGroupResourceId - ] - alertCriteriaType: 'Microsoft.Azure.Monitor.MultipleResourceMultipleMetricCriteria' - targetResourceRegion: 'westeurope' - targetResourceType: 'microsoft.compute/virtualmachines' - windowSize: 'PT15M' - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/insights/private-link-scope/main.bicep b/avm/res/insights/private-link-scope/main.bicep index 361702d546..e2c8e7f9d8 100644 --- a/avm/res/insights/private-link-scope/main.bicep +++ b/avm/res/insights/private-link-scope/main.bicep @@ -35,129 +35,184 @@ param enableTelemetry bool = true var 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') - 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') - 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') - 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') - 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') - 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Log Analytics Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '92aaf0da-9dab-42b6-94a3-d43ce8d16293' + ) + 'Log Analytics Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '73c42c96-874c-492b-b04d-ab87d138a893' + ) + 'Logic App Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '87a39d53-fc1b-424a-814c-f7e04687dc9e' + ) + 'Monitoring Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '749f88d5-cbae-40b8-bcfc-e573ddc772fa' + ) + 'Monitoring Metrics Publisher': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '3913510d-42f4-4e42-8a64-420c390055eb' + ) + 'Monitoring Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '43d0d8ad-25c7-4714-9337-8ba259a9fe05' + ) + 'Network Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '4d97b98b-1d4f-4787-a291-c67834d212e7' + ) Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') - 'Private DNS Zone Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f') + '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') - 'Tag Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4a9ae827-6dc8-4573-8ac7-8239d42aa03f') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Role Based Access Control Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' + ) + 'Tag Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '4a9ae827-6dc8-4573-8ac7-8239d42aa03f' + ) + 'User Access Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.insights-privatelinkscope.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.insights-privatelinkscope.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource privateLinkScope 'microsoft.insights/privateLinkScopes@2021-07-01-preview' = { name: name location: location tags: tags properties: { - accessModeSettings: !empty(privateEndpoints) ? { - ingestionAccessMode: accessModeSettings.?ingestionAccessMode ?? 'PrivateOnly' - queryAccessMode: accessModeSettings.?queryAccessMode ?? 'PrivateOnly' - exclusions: accessModeSettings.?exclusions ?? [] - } : accessModeSettings ?? { - ingestionAccessMode: accessModeSettings.?ingestionAccessMode ?? 'Open' - queryAccessMode: accessModeSettings.?queryAccessMode ?? 'Open' - exclusions: accessModeSettings.?exclusions ?? [] - } + accessModeSettings: !empty(privateEndpoints) + ? { + ingestionAccessMode: accessModeSettings.?ingestionAccessMode ?? 'PrivateOnly' + queryAccessMode: accessModeSettings.?queryAccessMode ?? 'PrivateOnly' + exclusions: accessModeSettings.?exclusions ?? [] + } + : accessModeSettings ?? { + ingestionAccessMode: accessModeSettings.?ingestionAccessMode ?? 'Open' + queryAccessMode: accessModeSettings.?queryAccessMode ?? 'Open' + exclusions: accessModeSettings.?exclusions ?? [] + } } } -module privateLinkScope_scopedResource 'scoped-resource/main.bicep' = [for (scopedResource, index) in (scopedResources ?? []): { - name: '${uniqueString(deployment().name, location)}-PrivateLinkScope-ScopedResource-${index}' - params: { - name: scopedResource.name - privateLinkScopeName: privateLinkScope.name - linkedResourceId: scopedResource.linkedResourceId +module privateLinkScope_scopedResource 'scoped-resource/main.bicep' = [ + for (scopedResource, index) in (scopedResources ?? []): { + name: '${uniqueString(deployment().name, location)}-PrivateLinkScope-ScopedResource-${index}' + params: { + name: scopedResource.name + privateLinkScopeName: privateLinkScope.name + linkedResourceId: scopedResource.linkedResourceId + } } -}] +] -resource privateLinkScope_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.' +resource privateLinkScope_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: privateLinkScope } - scope: privateLinkScope -} -module privateLinkScope_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-PrivateLinkScope-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(privateLinkScope.id, '/'))}-${privateEndpoint.?service ?? 'azuremonitor'}-${index}' - privateLinkServiceConnections: [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(privateLinkScope.id, '/'))}-${privateEndpoint.?service ?? 'azuremonitor'}-${index}' - properties: { - privateLinkServiceId: privateLinkScope.id - groupIds: [ - privateEndpoint.?service ?? 'azuremonitor' - ] +module privateLinkScope_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-PrivateLinkScope-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(privateLinkScope.id, '/'))}-${privateEndpoint.?service ?? 'azuremonitor'}-${index}' + privateLinkServiceConnections: [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(privateLinkScope.id, '/'))}-${privateEndpoint.?service ?? 'azuremonitor'}-${index}' + properties: { + privateLinkServiceId: privateLinkScope.id + groupIds: [ + privateEndpoint.?service ?? 'azuremonitor' + ] + } } - } - ] - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(privateLinkScope.id, '/'))}-${privateEndpoint.?service ?? 'azuremonitor'}-${index}' - properties: { - privateLinkServiceId: privateLinkScope.id - groupIds: [ - privateEndpoint.?service ?? 'azuremonitor' + ] + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(privateLinkScope.id, '/'))}-${privateEndpoint.?service ?? 'azuremonitor'}-${index}' + properties: { + privateLinkServiceId: privateLinkScope.id + groupIds: [ + privateEndpoint.?service ?? 'azuremonitor' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] +] -resource privateLinkScope_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(privateLinkScope.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource privateLinkScope_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(privateLinkScope.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: privateLinkScope } - scope: privateLinkScope -}] +] @description('The name of the private link scope.') output name string = privateLinkScope.name diff --git a/avm/res/insights/private-link-scope/main.json b/avm/res/insights/private-link-scope/main.json index 479a4c9333..b7948504fb 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.25.53.49325", - "templateHash": "9103650402015462975" + "version": "0.26.54.24096", + "templateHash": "15663862403424377072" }, "name": "Azure Monitor Private Link Scopes", "description": "This module deploys an Azure Monitor Private Link Scope.", @@ -550,8 +550,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14997816805234479909" + "version": "0.26.54.24096", + "templateHash": "4916941705691599780" }, "name": "Private Link Scope Scoped Resources", "description": "This module deploys a Private Link Scope Scoped Resource.", diff --git a/avm/res/insights/private-link-scope/scoped-resource/main.json b/avm/res/insights/private-link-scope/scoped-resource/main.json index 1c0c1180af..f721ddb2d6 100644 --- a/avm/res/insights/private-link-scope/scoped-resource/main.json +++ b/avm/res/insights/private-link-scope/scoped-resource/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14997816805234479909" + "version": "0.26.54.24096", + "templateHash": "4916941705691599780" }, "name": "Private Link Scope Scoped Resources", "description": "This module deploys a Private Link Scope Scoped Resource.", diff --git a/avm/res/insights/private-link-scope/tests/e2e/defaults/main.test.bicep b/avm/res/insights/private-link-scope/tests/e2e/defaults/main.test.bicep index 7b221cf51c..122e677443 100644 --- a/avm/res/insights/private-link-scope/tests/e2e/defaults/main.test.bicep +++ b/avm/res/insights/private-link-scope/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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: 'global' +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: 'global' + } } -}] +] diff --git a/avm/res/insights/private-link-scope/tests/e2e/max/main.test.bicep b/avm/res/insights/private-link-scope/tests/e2e/max/main.test.bicep index 30cc132bcc..5b2e9ec8d5 100644 --- a/avm/res/insights/private-link-scope/tests/e2e/max/main.test.bicep +++ b/avm/res/insights/private-link-scope/tests/e2e/max/main.test.bicep @@ -49,169 +49,174 @@ module nestedDependencies 'dependencies.bicep' = { var locationUpdated = toLower(replace(resourceLocation, ' ', '')) @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: 'global' - accessModeSettings: { - exclusions: [ +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: 'global' + accessModeSettings: { + exclusions: [ + { + ingestionAccessMode: 'PrivateOnly' + queryAccessMode: 'PrivateOnly' + privateEndpointConnectionName: 'thisisatest' + } + ] + ingestionAccessMode: 'Open' + queryAccessMode: 'Open' + } + scopedResources: [ { - ingestionAccessMode: 'PrivateOnly' - queryAccessMode: 'PrivateOnly' - privateEndpointConnectionName: 'thisisatest' + name: 'scoped1' + linkedResourceId: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId } ] - ingestionAccessMode: 'Open' - queryAccessMode: 'Open' - } - scopedResources: [ - { - name: 'scoped1' - linkedResourceId: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - privateEndpoints: [ - { - name: 'pe-${namePrefix}' - customNetworkInterfaceName: 'nic-pe-${namePrefix}' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + privateEndpoints: [ + { + name: 'pe-${namePrefix}' + customNetworkInterfaceName: 'nic-pe-${namePrefix}' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - ipConfigurations: [ - { - name: 'api' - properties: { - groupId: 'azuremonitor' - memberName: 'api' - privateIPAddress: '10.0.0.11' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' } - } - { - name: 'globalinai' - properties: { - groupId: 'azuremonitor' - memberName: 'global.in.ai' - privateIPAddress: '10.0.0.12' + ] + ipConfigurations: [ + { + name: 'api' + properties: { + groupId: 'azuremonitor' + memberName: 'api' + privateIPAddress: '10.0.0.11' + } } - } - { - name: 'profiler' - properties: { - groupId: 'azuremonitor' - memberName: 'profiler' - privateIPAddress: '10.0.0.13' + { + name: 'globalinai' + properties: { + groupId: 'azuremonitor' + memberName: 'global.in.ai' + privateIPAddress: '10.0.0.12' + } } - } - { - name: 'live' - properties: { - groupId: 'azuremonitor' - memberName: 'live' - privateIPAddress: '10.0.0.14' + { + name: 'profiler' + properties: { + groupId: 'azuremonitor' + memberName: 'profiler' + privateIPAddress: '10.0.0.13' + } } - } - { - name: 'diagservicesquery' - properties: { - groupId: 'azuremonitor' - memberName: 'diagservicesquery' - privateIPAddress: '10.0.0.15' + { + name: 'live' + properties: { + groupId: 'azuremonitor' + memberName: 'live' + privateIPAddress: '10.0.0.14' + } } - } - { - name: 'snapshot' - properties: { - groupId: 'azuremonitor' - memberName: 'snapshot' - privateIPAddress: '10.0.0.16' + { + name: 'diagservicesquery' + properties: { + groupId: 'azuremonitor' + memberName: 'diagservicesquery' + privateIPAddress: '10.0.0.15' + } } - } - { - name: 'agentsolutionpackstore' - properties: { - groupId: 'azuremonitor' - memberName: 'agentsolutionpackstore' - privateIPAddress: '10.0.0.17' + { + name: 'snapshot' + properties: { + groupId: 'azuremonitor' + memberName: 'snapshot' + privateIPAddress: '10.0.0.16' + } } - } - { - name: 'dce-global' - properties: { - groupId: 'azuremonitor' - memberName: 'dce-global' - privateIPAddress: '10.0.0.18' + { + name: 'agentsolutionpackstore' + properties: { + groupId: 'azuremonitor' + memberName: 'agentsolutionpackstore' + privateIPAddress: '10.0.0.17' + } } - } - { - name: 'oms-${locationUpdated}' - properties: { - groupId: 'azuremonitor' - memberName: 'oms-${locationUpdated}' - privateIPAddress: '10.0.0.19' + { + name: 'dce-global' + properties: { + groupId: 'azuremonitor' + memberName: 'dce-global' + privateIPAddress: '10.0.0.18' + } } - } - { - name: 'ods-${locationUpdated}' - properties: { - groupId: 'azuremonitor' - memberName: 'ods-${locationUpdated}' - privateIPAddress: '10.0.0.20' + { + name: 'oms-${locationUpdated}' + properties: { + groupId: 'azuremonitor' + memberName: 'oms-${locationUpdated}' + privateIPAddress: '10.0.0.19' + } } - } - { - name: 'agent-${locationUpdated}' - properties: { - groupId: 'azuremonitor' - memberName: 'agent-${locationUpdated}' - privateIPAddress: '10.0.0.21' + { + name: 'ods-${locationUpdated}' + properties: { + groupId: 'azuremonitor' + memberName: 'ods-${locationUpdated}' + privateIPAddress: '10.0.0.20' + } } - } - ] - } - ] - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + { + name: 'agent-${locationUpdated}' + properties: { + groupId: 'azuremonitor' + memberName: 'agent-${locationUpdated}' + privateIPAddress: '10.0.0.21' + } + } + ] + } + ] + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/insights/private-link-scope/tests/e2e/waf-aligned/main.test.bicep b/avm/res/insights/private-link-scope/tests/e2e/waf-aligned/main.test.bicep index 3dead88b70..c92cf66a1d 100644 --- a/avm/res/insights/private-link-scope/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/insights/private-link-scope/tests/e2e/waf-aligned/main.test.bicep @@ -47,130 +47,132 @@ module nestedDependencies 'dependencies.bicep' = { var locationUpdated = toLower(replace(resourceLocation, ' ', '')) @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: 'global' - scopedResources: [ - { - name: 'scoped1' - linkedResourceId: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - privateEndpoints: [ - { - name: 'pe-${namePrefix}' - customNetworkInterfaceName: 'nic-pe-${namePrefix}' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +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: 'global' + scopedResources: [ + { + name: 'scoped1' + linkedResourceId: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId } - ipConfigurations: [ - { - name: 'api' - properties: { - groupId: 'azuremonitor' - memberName: 'api' - privateIPAddress: '10.0.0.11' - } + ] + privateEndpoints: [ + { + name: 'pe-${namePrefix}' + customNetworkInterfaceName: 'nic-pe-${namePrefix}' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - { - name: 'globalinai' - properties: { - groupId: 'azuremonitor' - memberName: 'global.in.ai' - privateIPAddress: '10.0.0.12' + ipConfigurations: [ + { + name: 'api' + properties: { + groupId: 'azuremonitor' + memberName: 'api' + privateIPAddress: '10.0.0.11' + } } - } - { - name: 'profiler' - properties: { - groupId: 'azuremonitor' - memberName: 'profiler' - privateIPAddress: '10.0.0.13' + { + name: 'globalinai' + properties: { + groupId: 'azuremonitor' + memberName: 'global.in.ai' + privateIPAddress: '10.0.0.12' + } } - } - { - name: 'live' - properties: { - groupId: 'azuremonitor' - memberName: 'live' - privateIPAddress: '10.0.0.14' + { + name: 'profiler' + properties: { + groupId: 'azuremonitor' + memberName: 'profiler' + privateIPAddress: '10.0.0.13' + } } - } - { - name: 'diagservicesquery' - properties: { - groupId: 'azuremonitor' - memberName: 'diagservicesquery' - privateIPAddress: '10.0.0.15' + { + name: 'live' + properties: { + groupId: 'azuremonitor' + memberName: 'live' + privateIPAddress: '10.0.0.14' + } } - } - { - name: 'snapshot' - properties: { - groupId: 'azuremonitor' - memberName: 'snapshot' - privateIPAddress: '10.0.0.16' + { + name: 'diagservicesquery' + properties: { + groupId: 'azuremonitor' + memberName: 'diagservicesquery' + privateIPAddress: '10.0.0.15' + } } - } - { - name: 'agentsolutionpackstore' - properties: { - groupId: 'azuremonitor' - memberName: 'agentsolutionpackstore' - privateIPAddress: '10.0.0.17' + { + name: 'snapshot' + properties: { + groupId: 'azuremonitor' + memberName: 'snapshot' + privateIPAddress: '10.0.0.16' + } } - } - { - name: 'dce-global' - properties: { - groupId: 'azuremonitor' - memberName: 'dce-global' - privateIPAddress: '10.0.0.18' + { + name: 'agentsolutionpackstore' + properties: { + groupId: 'azuremonitor' + memberName: 'agentsolutionpackstore' + privateIPAddress: '10.0.0.17' + } } - } - { - name: 'oms-${locationUpdated}' - properties: { - groupId: 'azuremonitor' - memberName: 'oms-${locationUpdated}' - privateIPAddress: '10.0.0.19' + { + name: 'dce-global' + properties: { + groupId: 'azuremonitor' + memberName: 'dce-global' + privateIPAddress: '10.0.0.18' + } } - } - { - name: 'ods-${locationUpdated}' - properties: { - groupId: 'azuremonitor' - memberName: 'ods-${locationUpdated}' - privateIPAddress: '10.0.0.20' + { + name: 'oms-${locationUpdated}' + properties: { + groupId: 'azuremonitor' + memberName: 'oms-${locationUpdated}' + privateIPAddress: '10.0.0.19' + } } - } - { - name: 'agent-${locationUpdated}' - properties: { - groupId: 'azuremonitor' - memberName: 'agent-${locationUpdated}' - privateIPAddress: '10.0.0.21' + { + name: 'ods-${locationUpdated}' + properties: { + groupId: 'azuremonitor' + memberName: 'ods-${locationUpdated}' + privateIPAddress: '10.0.0.20' + } } - } - ] + { + name: 'agent-${locationUpdated}' + properties: { + groupId: 'azuremonitor' + memberName: 'agent-${locationUpdated}' + privateIPAddress: '10.0.0.21' + } + } + ] + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/insights/scheduled-query-rule/main.bicep b/avm/res/insights/scheduled-query-rule/main.bicep index 5c51cfacae..bea4edc69f 100644 --- a/avm/res/insights/scheduled-query-rule/main.bicep +++ b/avm/res/insights/scheduled-query-rule/main.bicep @@ -74,27 +74,34 @@ 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.insights-scheduledqueryrule.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.insights-scheduledqueryrule.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource queryRule 'Microsoft.Insights/scheduledQueryRules@2021-02-01-preview' = { name: name @@ -122,19 +129,25 @@ resource queryRule 'Microsoft.Insights/scheduledQueryRules@2021-02-01-preview' = } } -resource queryRule_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(queryRule.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource queryRule_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(queryRule.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: queryRule } - scope: queryRule -}] +] @description('The Name of the created scheduled query rule.') output name string = queryRule.name diff --git a/avm/res/insights/scheduled-query-rule/main.json b/avm/res/insights/scheduled-query-rule/main.json index 0e84461043..3f5f174495 100644 --- a/avm/res/insights/scheduled-query-rule/main.json +++ b/avm/res/insights/scheduled-query-rule/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17106717169874117365" + "version": "0.26.54.24096", + "templateHash": "11130634754232789940" }, "name": "Scheduled Query Rules", "description": "This module deploys a Scheduled Query Rule.", diff --git a/avm/res/insights/scheduled-query-rule/tests/e2e/defaults/dependencies.bicep b/avm/res/insights/scheduled-query-rule/tests/e2e/defaults/dependencies.bicep index cc24476629..63e7a207db 100644 --- a/avm/res/insights/scheduled-query-rule/tests/e2e/defaults/dependencies.bicep +++ b/avm/res/insights/scheduled-query-rule/tests/e2e/defaults/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param logAnalyticsWorkspaceName string resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' = { - name: logAnalyticsWorkspaceName - location: location + name: logAnalyticsWorkspaceName + location: location } @description('The resource ID of the created Log Analytics Workspace.') diff --git a/avm/res/insights/scheduled-query-rule/tests/e2e/defaults/main.test.bicep b/avm/res/insights/scheduled-query-rule/tests/e2e/defaults/main.test.bicep index 3c3f88928d..90dbf0cbfd 100644 --- a/avm/res/insights/scheduled-query-rule/tests/e2e/defaults/main.test.bicep +++ b/avm/res/insights/scheduled-query-rule/tests/e2e/defaults/main.test.bicep @@ -45,43 +45,45 @@ 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 - criterias: { - allOf: [ - { - dimensions: [ - { - name: 'Computer' - operator: 'Include' - values: [ - '*' - ] - } - { - name: 'InstanceName' - operator: 'Include' - values: [ - '*' - ] - } - ] - metricMeasureColumn: 'AggregatedValue' - operator: 'GreaterThan' - query: 'Perf | where ObjectName == "LogicalDisk" | where CounterName == "% Free Space" | where InstanceName <> "HarddiskVolume1" and InstanceName <> "_Total" | summarize AggregatedValue = min(CounterValue) by Computer, InstanceName, bin(TimeGenerated,5m)' - threshold: 0 - timeAggregation: 'Average' - } +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 + criterias: { + allOf: [ + { + dimensions: [ + { + name: 'Computer' + operator: 'Include' + values: [ + '*' + ] + } + { + name: 'InstanceName' + operator: 'Include' + values: [ + '*' + ] + } + ] + metricMeasureColumn: 'AggregatedValue' + operator: 'GreaterThan' + query: 'Perf | where ObjectName == "LogicalDisk" | where CounterName == "% Free Space" | where InstanceName <> "HarddiskVolume1" and InstanceName <> "_Total" | summarize AggregatedValue = min(CounterValue) by Computer, InstanceName, bin(TimeGenerated,5m)' + threshold: 0 + timeAggregation: 'Average' + } + ] + } + evaluationFrequency: 'PT5M' + scopes: [ + nestedDependencies.outputs.logAnalyticsWorkspaceResourceId ] + windowSize: 'PT5M' } - evaluationFrequency: 'PT5M' - scopes: [ - nestedDependencies.outputs.logAnalyticsWorkspaceResourceId - ] - windowSize: 'PT5M' } -}] +] diff --git a/avm/res/insights/scheduled-query-rule/tests/e2e/max/dependencies.bicep b/avm/res/insights/scheduled-query-rule/tests/e2e/max/dependencies.bicep index 9e9a8f2510..c4b3188814 100644 --- a/avm/res/insights/scheduled-query-rule/tests/e2e/max/dependencies.bicep +++ b/avm/res/insights/scheduled-query-rule/tests/e2e/max/dependencies.bicep @@ -8,13 +8,13 @@ param managedIdentityName string param logAnalyticsWorkspaceName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' = { - name: logAnalyticsWorkspaceName - location: location + name: logAnalyticsWorkspaceName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/insights/scheduled-query-rule/tests/e2e/max/main.test.bicep b/avm/res/insights/scheduled-query-rule/tests/e2e/max/main.test.bicep index bf15311fd2..372e4cebd7 100644 --- a/avm/res/insights/scheduled-query-rule/tests/e2e/max/main.test.bicep +++ b/avm/res/insights/scheduled-query-rule/tests/e2e/max/main.test.bicep @@ -46,69 +46,74 @@ 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 - alertDescription: 'My sample Alert' - autoMitigate: false - criterias: { - allOf: [ +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 + alertDescription: 'My sample Alert' + autoMitigate: false + criterias: { + allOf: [ + { + dimensions: [ + { + name: 'Computer' + operator: 'Include' + values: [ + '*' + ] + } + { + name: 'InstanceName' + operator: 'Include' + values: [ + '*' + ] + } + ] + metricMeasureColumn: 'AggregatedValue' + operator: 'GreaterThan' + query: 'Perf | where ObjectName == "LogicalDisk" | where CounterName == "% Free Space" | where InstanceName <> "HarddiskVolume1" and InstanceName <> "_Total" | summarize AggregatedValue = min(CounterValue) by Computer, InstanceName, bin(TimeGenerated,5m)' + threshold: 0 + timeAggregation: 'Average' + } + ] + } + evaluationFrequency: 'PT5M' + queryTimeRange: 'PT5M' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Owner' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } { - dimensions: [ - { - name: 'Computer' - operator: 'Include' - values: [ - '*' - ] - } - { - name: 'InstanceName' - operator: 'Include' - values: [ - '*' - ] - } - ] - metricMeasureColumn: 'AggregatedValue' - operator: 'GreaterThan' - query: 'Perf | where ObjectName == "LogicalDisk" | where CounterName == "% Free Space" | where InstanceName <> "HarddiskVolume1" and InstanceName <> "_Total" | summarize AggregatedValue = min(CounterValue) by Computer, InstanceName, bin(TimeGenerated,5m)' - threshold: 0 - timeAggregation: 'Average' + 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' } ] - } - evaluationFrequency: 'PT5M' - queryTimeRange: 'PT5M' - 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' + scopes: [ + nestedDependencies.outputs.logAnalyticsWorkspaceResourceId + ] + suppressForMinutes: 'PT5M' + windowSize: 'PT5M' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - scopes: [ - nestedDependencies.outputs.logAnalyticsWorkspaceResourceId - ] - suppressForMinutes: 'PT5M' - windowSize: 'PT5M' - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/insights/scheduled-query-rule/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/insights/scheduled-query-rule/tests/e2e/waf-aligned/dependencies.bicep index cc24476629..63e7a207db 100644 --- a/avm/res/insights/scheduled-query-rule/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/insights/scheduled-query-rule/tests/e2e/waf-aligned/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param logAnalyticsWorkspaceName string resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' = { - name: logAnalyticsWorkspaceName - location: location + name: logAnalyticsWorkspaceName + location: location } @description('The resource ID of the created Log Analytics Workspace.') diff --git a/avm/res/insights/scheduled-query-rule/tests/e2e/waf-aligned/main.test.bicep b/avm/res/insights/scheduled-query-rule/tests/e2e/waf-aligned/main.test.bicep index 9cc4ee9abb..911787cae6 100644 --- a/avm/res/insights/scheduled-query-rule/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/insights/scheduled-query-rule/tests/e2e/waf-aligned/main.test.bicep @@ -45,52 +45,54 @@ 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 - alertDescription: 'My sample Alert' - autoMitigate: false - criterias: { - allOf: [ - { - dimensions: [ - { - name: 'Computer' - operator: 'Include' - values: [ - '*' - ] - } - { - name: 'InstanceName' - operator: 'Include' - values: [ - '*' - ] - } - ] - metricMeasureColumn: 'AggregatedValue' - operator: 'GreaterThan' - query: 'Perf | where ObjectName == "LogicalDisk" | where CounterName == "% Free Space" | where InstanceName <> "HarddiskVolume1" and InstanceName <> "_Total" | summarize AggregatedValue = min(CounterValue) by Computer, InstanceName, bin(TimeGenerated,5m)' - threshold: 0 - timeAggregation: 'Average' - } +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 + alertDescription: 'My sample Alert' + autoMitigate: false + criterias: { + allOf: [ + { + dimensions: [ + { + name: 'Computer' + operator: 'Include' + values: [ + '*' + ] + } + { + name: 'InstanceName' + operator: 'Include' + values: [ + '*' + ] + } + ] + metricMeasureColumn: 'AggregatedValue' + operator: 'GreaterThan' + query: 'Perf | where ObjectName == "LogicalDisk" | where CounterName == "% Free Space" | where InstanceName <> "HarddiskVolume1" and InstanceName <> "_Total" | summarize AggregatedValue = min(CounterValue) by Computer, InstanceName, bin(TimeGenerated,5m)' + threshold: 0 + timeAggregation: 'Average' + } + ] + } + evaluationFrequency: 'PT5M' + queryTimeRange: 'PT5M' + scopes: [ + nestedDependencies.outputs.logAnalyticsWorkspaceResourceId ] - } - evaluationFrequency: 'PT5M' - queryTimeRange: 'PT5M' - scopes: [ - nestedDependencies.outputs.logAnalyticsWorkspaceResourceId - ] - suppressForMinutes: 'PT5M' - windowSize: 'PT5M' - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + suppressForMinutes: 'PT5M' + windowSize: 'PT5M' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } } -}] +] diff --git a/avm/res/insights/webtest/main.bicep b/avm/res/insights/webtest/main.bicep index 1b788fd240..8bca15afd2 100644 --- a/avm/res/insights/webtest/main.bicep +++ b/avm/res/insights/webtest/main.bicep @@ -88,27 +88,34 @@ 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.insights-webtest.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.insights-webtest.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource webtest 'Microsoft.Insights/webtests@2022-06-15' = { name: name @@ -130,28 +137,37 @@ resource webtest 'Microsoft.Insights/webtests@2022-06-15' = { } } -resource webtest_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.' +resource webtest_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: webtest } - scope: webtest -} -resource webtest_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(webtest.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource webtest_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(webtest.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: webtest } - scope: webtest -}] +] @sys.description('The name of the webtest.') output name string = webtest.name diff --git a/avm/res/insights/webtest/main.json b/avm/res/insights/webtest/main.json index 246ccae4f5..fbf790faf9 100644 --- a/avm/res/insights/webtest/main.json +++ b/avm/res/insights/webtest/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16473822871746404569" + "version": "0.26.54.24096", + "templateHash": "279019710662992731" }, "name": "Web Tests", "description": "This module deploys a Web Test.", diff --git a/avm/res/insights/webtest/tests/e2e/defaults/main.test.bicep b/avm/res/insights/webtest/tests/e2e/defaults/main.test.bicep index 2415c915c7..dc52027e62 100644 --- a/avm/res/insights/webtest/tests/e2e/defaults/main.test.bicep +++ b/avm/res/insights/webtest/tests/e2e/defaults/main.test.bicep @@ -46,17 +46,19 @@ 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 - appInsightResourceId: nestedDependencies.outputs.appInsightResourceId - webTestName: 'wt${namePrefix}$${serviceShort}001' - request: { - RequestUrl: 'https://learn.microsoft.com/en-us/' - HttpVerb: 'GET' +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 + appInsightResourceId: nestedDependencies.outputs.appInsightResourceId + webTestName: 'wt${namePrefix}$${serviceShort}001' + request: { + RequestUrl: 'https://learn.microsoft.com/en-us/' + HttpVerb: 'GET' + } } } -}] +] diff --git a/avm/res/insights/webtest/tests/e2e/max/main.test.bicep b/avm/res/insights/webtest/tests/e2e/max/main.test.bicep index 55c279f0b1..351a8baa6e 100644 --- a/avm/res/insights/webtest/tests/e2e/max/main.test.bicep +++ b/avm/res/insights/webtest/tests/e2e/max/main.test.bicep @@ -47,49 +47,54 @@ 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 - appInsightResourceId: nestedDependencies.outputs.appInsightResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - webTestName: 'wt${namePrefix}$${serviceShort}001' - syntheticMonitorId: '${namePrefix}${serviceShort}001' - locations: [ - { - Id: 'emea-nl-ams-azr' - } - ] - request: { - RequestUrl: 'https://learn.microsoft.com/en-us/' - HttpVerb: 'GET' - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +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 + appInsightResourceId: nestedDependencies.outputs.appInsightResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + webTestName: 'wt${namePrefix}$${serviceShort}001' + syntheticMonitorId: '${namePrefix}${serviceShort}001' + locations: [ + { + Id: 'emea-nl-ams-azr' + } + ] + request: { + RequestUrl: 'https://learn.microsoft.com/en-us/' + HttpVerb: 'GET' } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + 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' + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' } } -}] +] diff --git a/avm/res/insights/webtest/tests/e2e/waf-aligned/main.test.bicep b/avm/res/insights/webtest/tests/e2e/waf-aligned/main.test.bicep index bccb92e4f7..11a413e559 100644 --- a/avm/res/insights/webtest/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/insights/webtest/tests/e2e/waf-aligned/main.test.bicep @@ -46,26 +46,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 - appInsightResourceId: nestedDependencies.outputs.appInsightResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - } - webTestName: 'wt${namePrefix}$${serviceShort}001' - syntheticMonitorId: '${namePrefix}${serviceShort}001' - locations: [ - { - Id: 'emea-nl-ams-azr' +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 + appInsightResourceId: nestedDependencies.outputs.appInsightResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + } + webTestName: 'wt${namePrefix}$${serviceShort}001' + syntheticMonitorId: '${namePrefix}${serviceShort}001' + locations: [ + { + Id: 'emea-nl-ams-azr' + } + ] + request: { + RequestUrl: 'https://learn.microsoft.com/en-us/' + HttpVerb: 'GET' } - ] - request: { - RequestUrl: 'https://learn.microsoft.com/en-us/' - HttpVerb: 'GET' } } -}] +] diff --git a/avm/res/kubernetes-configuration/extension/main.bicep b/avm/res/kubernetes-configuration/extension/main.bicep index 741d911002..68b991b60e 100644 --- a/avm/res/kubernetes-configuration/extension/main.bicep +++ b/avm/res/kubernetes-configuration/extension/main.bicep @@ -39,23 +39,24 @@ param version string? @description('Optional. A list of flux configuraitons.') param fluxConfigurations array? -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.kubernetesconfiguration-extension.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.kubernetesconfiguration-extension.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource managedCluster 'Microsoft.ContainerService/managedClusters@2022-07-01' existing = { name: clusterName @@ -71,36 +72,42 @@ resource extension 'Microsoft.KubernetesConfiguration/extensions@2022-03-01' = { extensionType: extensionType releaseTrain: releaseTrain scope: { - cluster: !empty(releaseNamespace ?? '') ? { - releaseNamespace: releaseNamespace - } : null - namespace: !empty(targetNamespace ?? '') ? { - targetNamespace: targetNamespace - } : null + cluster: !empty(releaseNamespace ?? '') + ? { + releaseNamespace: releaseNamespace + } + : null + namespace: !empty(targetNamespace ?? '') + ? { + targetNamespace: targetNamespace + } + : null } version: version } } -module fluxConfiguration 'br/public:avm/res/kubernetes-configuration/flux-configuration:0.3.1' = [for (fluxConfiguration, index) in (fluxConfigurations ?? []): { - name: '${uniqueString(deployment().name, location)}-ManagedCluster-FluxConfiguration${index}' - params: { - enableTelemetry: fluxConfiguration.?enableTelemetry ?? enableTelemetry - clusterName: managedCluster.name - scope: fluxConfiguration.scope - namespace: fluxConfiguration.namespace - sourceKind: contains(fluxConfiguration, 'gitRepository') ? 'GitRepository' : 'Bucket' - name: fluxConfiguration.?name ?? toLower('${managedCluster.name}-fluxconfiguration${index}') - bucket: fluxConfiguration.?bucket - configurationProtectedSettings: fluxConfiguration.?configurationProtectedSettings - gitRepository: fluxConfiguration.?gitRepository - kustomizations: fluxConfiguration.kustomizations - suspend: fluxConfiguration.?suspend +module fluxConfiguration 'br/public:avm/res/kubernetes-configuration/flux-configuration:0.3.1' = [ + for (fluxConfiguration, index) in (fluxConfigurations ?? []): { + name: '${uniqueString(deployment().name, location)}-ManagedCluster-FluxConfiguration${index}' + params: { + enableTelemetry: fluxConfiguration.?enableTelemetry ?? enableTelemetry + clusterName: managedCluster.name + scope: fluxConfiguration.scope + namespace: fluxConfiguration.namespace + sourceKind: contains(fluxConfiguration, 'gitRepository') ? 'GitRepository' : 'Bucket' + name: fluxConfiguration.?name ?? toLower('${managedCluster.name}-fluxconfiguration${index}') + bucket: fluxConfiguration.?bucket + configurationProtectedSettings: fluxConfiguration.?configurationProtectedSettings + gitRepository: fluxConfiguration.?gitRepository + kustomizations: fluxConfiguration.kustomizations + suspend: fluxConfiguration.?suspend + } + dependsOn: [ + extension + ] } - dependsOn: [ - extension - ] -}] +] @description('The name of the extension.') output name string = extension.name diff --git a/avm/res/kubernetes-configuration/extension/main.json b/avm/res/kubernetes-configuration/extension/main.json index a79e84ead3..c85c779228 100644 --- a/avm/res/kubernetes-configuration/extension/main.json +++ b/avm/res/kubernetes-configuration/extension/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "7131693872347776073" + "version": "0.26.54.24096", + "templateHash": "18185878129921547282" }, "name": "Kubernetes Configuration Extensions", "description": "This module deploys a Kubernetes Configuration Extension.", diff --git a/avm/res/kubernetes-configuration/extension/tests/e2e/defaults/main.test.bicep b/avm/res/kubernetes-configuration/extension/tests/e2e/defaults/main.test.bicep index a71469af7c..b46932fa1c 100644 --- a/avm/res/kubernetes-configuration/extension/tests/e2e/defaults/main.test.bicep +++ b/avm/res/kubernetes-configuration/extension/tests/e2e/defaults/main.test.bicep @@ -45,18 +45,20 @@ 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 - clusterName: nestedDependencies.outputs.clusterName - extensionType: 'microsoft.flux' - releaseNamespace: 'flux-system' - releaseTrain: 'Stable' +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 + clusterName: nestedDependencies.outputs.clusterName + extensionType: 'microsoft.flux' + releaseNamespace: 'flux-system' + releaseTrain: 'Stable' + } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/kubernetes-configuration/extension/tests/e2e/max/main.test.bicep b/avm/res/kubernetes-configuration/extension/tests/e2e/max/main.test.bicep index 1d299f95bd..835be36f07 100644 --- a/avm/res/kubernetes-configuration/extension/tests/e2e/max/main.test.bicep +++ b/avm/res/kubernetes-configuration/extension/tests/e2e/max/main.test.bicep @@ -46,47 +46,49 @@ 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 - clusterName: nestedDependencies.outputs.clusterName - extensionType: 'microsoft.flux' - configurationSettings: { - 'image-automation-controller.enabled': 'false' - 'image-reflector-controller.enabled': 'false' - 'kustomize-controller.enabled': 'true' - 'notification-controller.enabled': 'false' - 'source-controller.enabled': 'true' - } - releaseNamespace: 'flux-system' - releaseTrain: 'Stable' - version: '0.5.2' - fluxConfigurations: [ - { - namespace: 'flux-system' - scope: 'cluster' - gitRepository: { - repositoryRef: { - branch: 'main' +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 + clusterName: nestedDependencies.outputs.clusterName + extensionType: 'microsoft.flux' + configurationSettings: { + 'image-automation-controller.enabled': 'false' + 'image-reflector-controller.enabled': 'false' + 'kustomize-controller.enabled': 'true' + 'notification-controller.enabled': 'false' + 'source-controller.enabled': 'true' + } + releaseNamespace: 'flux-system' + releaseTrain: 'Stable' + version: '0.5.2' + fluxConfigurations: [ + { + namespace: 'flux-system' + scope: 'cluster' + gitRepository: { + repositoryRef: { + branch: 'main' + } + sshKnownHosts: '' + syncIntervalInSeconds: 300 + timeoutInSeconds: 180 + url: 'https://github.com/mspnp/aks-baseline' } - sshKnownHosts: '' - syncIntervalInSeconds: 300 - timeoutInSeconds: 180 - url: 'https://github.com/mspnp/aks-baseline' - } - kustomizations: { - unified: { - path: './cluster-manifests' + kustomizations: { + unified: { + path: './cluster-manifests' + } } + suspend: false } - suspend: false - } + ] + } + dependsOn: [ + nestedDependencies ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/kubernetes-configuration/extension/tests/e2e/waf-aligned/main.test.bicep b/avm/res/kubernetes-configuration/extension/tests/e2e/waf-aligned/main.test.bicep index b9078ed104..b9fb8d1047 100644 --- a/avm/res/kubernetes-configuration/extension/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/kubernetes-configuration/extension/tests/e2e/waf-aligned/main.test.bicep @@ -46,47 +46,49 @@ 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 - clusterName: nestedDependencies.outputs.clusterName - extensionType: 'microsoft.flux' - configurationSettings: { - 'image-automation-controller.enabled': 'false' - 'image-reflector-controller.enabled': 'false' - 'kustomize-controller.enabled': 'true' - 'notification-controller.enabled': 'false' - 'source-controller.enabled': 'true' - } - releaseNamespace: 'flux-system' - releaseTrain: 'Stable' - version: '0.5.2' - fluxConfigurations: [ - { - namespace: 'flux-system' - scope: 'cluster' - gitRepository: { - repositoryRef: { - branch: 'main' +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 + clusterName: nestedDependencies.outputs.clusterName + extensionType: 'microsoft.flux' + configurationSettings: { + 'image-automation-controller.enabled': 'false' + 'image-reflector-controller.enabled': 'false' + 'kustomize-controller.enabled': 'true' + 'notification-controller.enabled': 'false' + 'source-controller.enabled': 'true' + } + releaseNamespace: 'flux-system' + releaseTrain: 'Stable' + version: '0.5.2' + fluxConfigurations: [ + { + namespace: 'flux-system' + scope: 'cluster' + gitRepository: { + repositoryRef: { + branch: 'main' + } + sshKnownHosts: '' + syncIntervalInSeconds: 300 + timeoutInSeconds: 180 + url: 'https://github.com/mspnp/aks-baseline' } - sshKnownHosts: '' - syncIntervalInSeconds: 300 - timeoutInSeconds: 180 - url: 'https://github.com/mspnp/aks-baseline' - } - kustomizations: { - unified: { - path: './cluster-manifests' + kustomizations: { + unified: { + path: './cluster-manifests' + } } + suspend: false } - suspend: false - } + ] + } + dependsOn: [ + nestedDependencies ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/kubernetes-configuration/flux-configuration/main.bicep b/avm/res/kubernetes-configuration/flux-configuration/main.bicep index d20f80e3e8..902f352b66 100644 --- a/avm/res/kubernetes-configuration/flux-configuration/main.bicep +++ b/avm/res/kubernetes-configuration/flux-configuration/main.bicep @@ -47,23 +47,24 @@ param sourceKind string @description('Optional. Whether this configuration should suspend its reconciliation of its kustomizations and sources.') param suspend bool = false -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.kubernetesconfiguration-fluxconfig.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.kubernetesconfiguration-fluxconfig.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource managedCluster 'Microsoft.ContainerService/managedClusters@2022-07-01' existing = { name: clusterName diff --git a/avm/res/kubernetes-configuration/flux-configuration/main.json b/avm/res/kubernetes-configuration/flux-configuration/main.json index 6cd90c53c6..531c562fa1 100644 --- a/avm/res/kubernetes-configuration/flux-configuration/main.json +++ b/avm/res/kubernetes-configuration/flux-configuration/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17949418893063624330" + "version": "0.26.54.24096", + "templateHash": "5850792806507194652" }, "name": "Kubernetes Configuration Flux Configurations", "description": "This module deploys a Kubernetes Configuration Flux Configuration.", diff --git a/avm/res/kubernetes-configuration/flux-configuration/tests/e2e/defaults/main.test.bicep b/avm/res/kubernetes-configuration/flux-configuration/tests/e2e/defaults/main.test.bicep index d9f8504c7e..430f6d59a3 100644 --- a/avm/res/kubernetes-configuration/flux-configuration/tests/e2e/defaults/main.test.bicep +++ b/avm/res/kubernetes-configuration/flux-configuration/tests/e2e/defaults/main.test.bicep @@ -47,32 +47,34 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - clusterName: nestedDependencies.outputs.clusterName - namespace: 'flux-system' - scope: 'cluster' - sourceKind: 'GitRepository' - gitRepository: { - repositoryRef: { - branch: 'main' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + clusterName: nestedDependencies.outputs.clusterName + namespace: 'flux-system' + scope: 'cluster' + sourceKind: 'GitRepository' + gitRepository: { + repositoryRef: { + branch: 'main' + } + sshKnownHosts: '' + syncIntervalInSeconds: 300 + timeoutInSeconds: 180 + url: 'https://github.com/mspnp/aks-baseline' } - sshKnownHosts: '' - syncIntervalInSeconds: 300 - timeoutInSeconds: 180 - url: 'https://github.com/mspnp/aks-baseline' - } - kustomizations: { - unified: { - path: './cluster-manifests' + kustomizations: { + unified: { + path: './cluster-manifests' + } } } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/kubernetes-configuration/flux-configuration/tests/e2e/max/main.test.bicep b/avm/res/kubernetes-configuration/flux-configuration/tests/e2e/max/main.test.bicep index 10a9bbd4eb..0545b6e5c9 100644 --- a/avm/res/kubernetes-configuration/flux-configuration/tests/e2e/max/main.test.bicep +++ b/avm/res/kubernetes-configuration/flux-configuration/tests/e2e/max/main.test.bicep @@ -47,43 +47,45 @@ 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 - clusterName: nestedDependencies.outputs.clusterName - namespace: 'flux-system' - scope: 'cluster' - sourceKind: 'GitRepository' - gitRepository: { - repositoryRef: { - branch: 'main' - } - sshKnownHosts: '' - syncIntervalInSeconds: 300 - timeoutInSeconds: 180 - url: 'https://github.com/mspnp/aks-baseline' - } - kustomizations: { - unified: { - dependsOn: [] - force: false - path: './cluster-manifests' - prune: true +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 + clusterName: nestedDependencies.outputs.clusterName + namespace: 'flux-system' + scope: 'cluster' + sourceKind: 'GitRepository' + gitRepository: { + repositoryRef: { + branch: 'main' + } + sshKnownHosts: '' syncIntervalInSeconds: 300 - timeoutInSeconds: 300 - postBuild: { - substitute: { - TEST_VAR1: 'foo' - TEST_VAR2: 'bar' + timeoutInSeconds: 180 + url: 'https://github.com/mspnp/aks-baseline' + } + kustomizations: { + unified: { + dependsOn: [] + force: false + path: './cluster-manifests' + prune: true + syncIntervalInSeconds: 300 + timeoutInSeconds: 300 + postBuild: { + substitute: { + TEST_VAR1: 'foo' + TEST_VAR2: 'bar' + } } } } } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/kubernetes-configuration/flux-configuration/tests/e2e/waf-aligned/main.test.bicep b/avm/res/kubernetes-configuration/flux-configuration/tests/e2e/waf-aligned/main.test.bicep index 148f5acfbd..10516046be 100644 --- a/avm/res/kubernetes-configuration/flux-configuration/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/kubernetes-configuration/flux-configuration/tests/e2e/waf-aligned/main.test.bicep @@ -47,37 +47,39 @@ 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' - clusterName: nestedDependencies.outputs.clusterName - namespace: 'flux-system' - location: resourceLocation - scope: 'cluster' - sourceKind: 'GitRepository' - gitRepository: { - repositoryRef: { - branch: 'main' - } - sshKnownHosts: '' - syncIntervalInSeconds: 300 - timeoutInSeconds: 180 - url: 'https://github.com/mspnp/aks-baseline' - } - kustomizations: { - unified: { - dependsOn: [] - force: false - path: './cluster-manifests' - prune: true +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + clusterName: nestedDependencies.outputs.clusterName + namespace: 'flux-system' + location: resourceLocation + scope: 'cluster' + sourceKind: 'GitRepository' + gitRepository: { + repositoryRef: { + branch: 'main' + } + sshKnownHosts: '' syncIntervalInSeconds: 300 - timeoutInSeconds: 300 + timeoutInSeconds: 180 + url: 'https://github.com/mspnp/aks-baseline' + } + kustomizations: { + unified: { + dependsOn: [] + force: false + path: './cluster-manifests' + prune: true + syncIntervalInSeconds: 300 + timeoutInSeconds: 300 + } } } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/machine-learning-services/workspace/compute/main.bicep b/avm/res/machine-learning-services/workspace/compute/main.bicep index e135ccbfef..70064ee383 100644 --- a/avm/res/machine-learning-services/workspace/compute/main.bicep +++ b/avm/res/machine-learning-services/workspace/compute/main.bicep @@ -71,12 +71,20 @@ param managedIdentities managedIdentitiesType // 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 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 // ============================= // // Existing resources references // @@ -90,27 +98,35 @@ resource machineLearningWorkspace 'Microsoft.MachineLearningServices/workspaces@ // Deployments // // ============ // -resource compute 'Microsoft.MachineLearningServices/workspaces/computes@2022-10-01' = if (deployCompute == true) { - name: name - location: location - tags: empty(resourceId) ? tags : any(null) - sku: empty(resourceId) ? { - name: sku - tier: sku - } : any(null) - parent: machineLearningWorkspace - identity: empty(resourceId) ? identity : any(null) - properties: union({ - description: description - disableLocalAuth: disableLocalAuth - computeType: computeType - }, (!empty(resourceId) ? { - resourceId: resourceId - } : { - computeLocation: computeLocation - properties: properties - })) -} +resource compute 'Microsoft.MachineLearningServices/workspaces/computes@2022-10-01' = + if (deployCompute == true) { + name: name + location: location + tags: empty(resourceId) ? tags : any(null) + sku: empty(resourceId) + ? { + name: sku + tier: sku + } + : any(null) + parent: machineLearningWorkspace + identity: empty(resourceId) ? identity : any(null) + properties: union( + { + description: description + disableLocalAuth: disableLocalAuth + computeType: computeType + }, + (!empty(resourceId) + ? { + resourceId: resourceId + } + : { + computeLocation: computeLocation + properties: properties + }) + ) + } // =========== // // Outputs // diff --git a/avm/res/machine-learning-services/workspace/compute/main.json b/avm/res/machine-learning-services/workspace/compute/main.json index ba90995b69..e1be6424e3 100644 --- a/avm/res/machine-learning-services/workspace/compute/main.json +++ b/avm/res/machine-learning-services/workspace/compute/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2960011886227478748" + "version": "0.26.54.24096", + "templateHash": "2355820538616279194" }, "name": "Machine Learning Services Workspaces Computes", "description": "This module deploys a Machine Learning Services Workspaces Compute.\n\nAttaching a compute is not idempotent and will fail in case you try to redeploy over an existing compute in AML (see parameter `deployCompute`).", diff --git a/avm/res/machine-learning-services/workspace/main.bicep b/avm/res/machine-learning-services/workspace/main.bicep index a60169b526..ece1f942f0 100644 --- a/avm/res/machine-learning-services/workspace/main.bicep +++ b/avm/res/machine-learning-services/workspace/main.bicep @@ -98,59 +98,95 @@ param publicNetworkAccess string? // 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' : 'None') - userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null -} : null +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' : 'None') + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null + } + : null // ================// // Deployments // // ================// var builtInRoleNames = { - 'AzureML Compute Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e503ece1-11d0-4e8e-8e2c-7a6c3bf38815') - 'AzureML Data Scientist': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f6c7c914-8db3-469d-8ca1-694a8f32e121') - 'AzureML Metrics Writer (preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '635dd51f-9968-44d3-b7fb-6d9a6bd613ae') - 'AzureML Registry User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1823dd4f-9b8c-4ab6-ab4e-7397a3684615') + 'AzureML Compute Operator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'e503ece1-11d0-4e8e-8e2c-7a6c3bf38815' + ) + 'AzureML Data Scientist': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f6c7c914-8db3-469d-8ca1-694a8f32e121' + ) + 'AzureML Metrics Writer (preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '635dd51f-9968-44d3-b7fb-6d9a6bd613ae' + ) + 'AzureML Registry User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '1823dd4f-9b8c-4ab6-ab4e-7397a3684615' + ) 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.machinelearningservices-workspace.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.machinelearningservices-workspace.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} - -resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId)) { - name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) - scope: resourceGroup(split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4]) - resource cMKKey 'keys@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { - name: customerManagedKey.?keyName ?? 'dummyKey' +resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = + if (!empty(customerManagedKey.?keyVaultResourceId)) { + name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) + scope: resourceGroup( + split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], + split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4] + ) + + resource cMKKey 'keys@2023-02-01' existing = + if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { + name: customerManagedKey.?keyName ?? 'dummyKey' + } } -} -resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { - name: last(split(customerManagedKey.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) - scope: resourceGroup(split((customerManagedKey.?userAssignedIdentityResourceId ?? '//'), '/')[2], split((customerManagedKey.?userAssignedIdentityResourceId ?? '////'), '/')[4]) -} +resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = + if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { + name: last(split(customerManagedKey.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) + scope: resourceGroup( + split((customerManagedKey.?userAssignedIdentityResourceId ?? '//'), '/')[2], + split((customerManagedKey.?userAssignedIdentityResourceId ?? '////'), '/')[4] + ) + } resource workspace 'Microsoft.MachineLearningServices/workspaces@2022-10-01' = { name: name @@ -173,137 +209,174 @@ resource workspace 'Microsoft.MachineLearningServices/workspaces@2022-10-01' = { allowPublicAccessWhenBehindVnet: allowPublicAccessWhenBehindVnet description: description discoveryUrl: discoveryUrl - encryption: !empty(customerManagedKey) ? { - status: 'Enabled' - identity: !empty(customerManagedKey.?userAssignedIdentityResourceId) ? { - userAssignedIdentity: cMKUserAssignedIdentity.id - } : null - keyVaultProperties: { - keyVaultArmId: cMKKeyVault.id - keyIdentifier: !empty(customerManagedKey.?keyVersion ?? '') ? '${cMKKeyVault::cMKKey.properties.keyUri}/${customerManagedKey!.keyVersion}' : cMKKeyVault::cMKKey.properties.keyUriWithVersion - } - } : null + encryption: !empty(customerManagedKey) + ? { + status: 'Enabled' + identity: !empty(customerManagedKey.?userAssignedIdentityResourceId) + ? { + userAssignedIdentity: cMKUserAssignedIdentity.id + } + : null + keyVaultProperties: { + keyVaultArmId: cMKKeyVault.id + keyIdentifier: !empty(customerManagedKey.?keyVersion ?? '') + ? '${cMKKeyVault::cMKKey.properties.keyUri}/${customerManagedKey!.keyVersion}' + : cMKKeyVault::cMKKey.properties.keyUriWithVersion + } + } + : null imageBuildCompute: imageBuildCompute primaryUserAssignedIdentity: primaryUserAssignedIdentity - publicNetworkAccess: !empty(publicNetworkAccess) ? any(publicNetworkAccess) : (!empty(privateEndpoints) ? 'Disabled' : 'Enabled') + publicNetworkAccess: !empty(publicNetworkAccess) + ? any(publicNetworkAccess) + : (!empty(privateEndpoints) ? 'Disabled' : 'Enabled') serviceManagedResourcesSettings: serviceManagedResourcesSettings }, // Parameters only added if not empty - !empty(sharedPrivateLinkResources) ? { - sharedPrivateLinkResources: sharedPrivateLinkResources - } : {} + !empty(sharedPrivateLinkResources) + ? { + sharedPrivateLinkResources: sharedPrivateLinkResources + } + : {} ) } -module workspace_computes 'compute/main.bicep' = [for compute in (computes ?? []): { - name: '${workspace.name}-${compute.name}-compute' - params: { - machineLearningWorkspaceName: workspace.name - name: compute.name - location: compute.location - sku: compute.?sku - managedIdentities: compute.?managedIdentities - tags: compute.?tags - deployCompute: compute.?deployCompute - computeLocation: compute.?computeLocation - description: compute.?description - disableLocalAuth: compute.?disableLocalAuth - resourceId: compute.?resourceId - computeType: compute.computeType - properties: compute.?properties +module workspace_computes 'compute/main.bicep' = [ + for compute in (computes ?? []): { + name: '${workspace.name}-${compute.name}-compute' + params: { + machineLearningWorkspaceName: workspace.name + name: compute.name + location: compute.location + sku: compute.?sku + managedIdentities: compute.?managedIdentities + tags: compute.?tags + deployCompute: compute.?deployCompute + computeLocation: compute.?computeLocation + description: compute.?description + disableLocalAuth: compute.?disableLocalAuth + resourceId: compute.?resourceId + computeType: compute.computeType + properties: compute.?properties + } + dependsOn: [ + workspace_privateEndpoints + ] } - dependsOn: [ - workspace_privateEndpoints - ] -}] - -resource workspace_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.' +] + +resource workspace_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: workspace } - scope: workspace -} -resource workspace_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource workspace_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: workspace } - scope: workspace -}] - -module workspace_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.1' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-workspace-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(workspace.id, '/'))}-${privateEndpoint.?service ?? 'amlworkspace'}-${index}' - privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(workspace.id, '/'))}-${privateEndpoint.?service ?? 'amlworkspace'}-${index}' - properties: { - privateLinkServiceId: workspace.id - groupIds: [ - privateEndpoint.?service ?? 'amlworkspace' +] + +module workspace_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.1' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-workspace-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(workspace.id, '/'))}-${privateEndpoint.?service ?? 'amlworkspace'}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(workspace.id, '/'))}-${privateEndpoint.?service ?? 'amlworkspace'}-${index}' + properties: { + privateLinkServiceId: workspace.id + groupIds: [ + privateEndpoint.?service ?? 'amlworkspace' + ] + } + } ] - } - } - ] : null - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(workspace.id, '/'))}-${privateEndpoint.?service ?? 'amlworkspace'}-${index}' - properties: { - privateLinkServiceId: workspace.id - groupIds: [ - privateEndpoint.?service ?? 'amlworkspace' + : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(workspace.id, '/'))}-${privateEndpoint.?service ?? 'amlworkspace'}-${index}' + properties: { + privateLinkServiceId: workspace.id + groupIds: [ + privateEndpoint.?service ?? 'amlworkspace' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] - -resource workspace_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(workspace.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +] + +resource workspace_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(workspace.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: workspace } - scope: workspace -}] +] // ================// // Outputs // diff --git a/avm/res/machine-learning-services/workspace/main.json b/avm/res/machine-learning-services/workspace/main.json index 7af12d178a..d11a6904f5 100644 --- a/avm/res/machine-learning-services/workspace/main.json +++ b/avm/res/machine-learning-services/workspace/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2153747383305102474" + "version": "0.26.54.24096", + "templateHash": "16054212084136992012" }, "name": "Machine Learning Services Workspaces", "description": "This module deploys a Machine Learning Services Workspace.", @@ -861,8 +861,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2960011886227478748" + "version": "0.26.54.24096", + "templateHash": "2355820538616279194" }, "name": "Machine Learning Services Workspaces Computes", "description": "This module deploys a Machine Learning Services Workspaces Compute.\n\nAttaching a compute is not idempotent and will fail in case you try to redeploy over an existing compute in AML (see parameter `deployCompute`).", diff --git a/avm/res/machine-learning-services/workspace/tests/e2e/defaults/dependencies.bicep b/avm/res/machine-learning-services/workspace/tests/e2e/defaults/dependencies.bicep index 950a61c9f9..6ddec13775 100644 --- a/avm/res/machine-learning-services/workspace/tests/e2e/defaults/dependencies.bicep +++ b/avm/res/machine-learning-services/workspace/tests/e2e/defaults/dependencies.bicep @@ -11,37 +11,37 @@ param applicationInsightsName string param storageAccountName string 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: [] + 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 applicationInsights 'Microsoft.Insights/components@2020-02-02' = { - name: applicationInsightsName - location: location - kind: '' - properties: {} + name: applicationInsightsName + location: location + kind: '' + properties: {} } resource storageAccount 'Microsoft.Storage/storageAccounts@2021-09-01' = { - name: storageAccountName - location: location - sku: { - name: 'Standard_LRS' - } - kind: 'StorageV2' + name: storageAccountName + location: location + sku: { + name: 'Standard_LRS' + } + kind: 'StorageV2' } @description('The resource ID of the created Application Insights instance.') diff --git a/avm/res/machine-learning-services/workspace/tests/e2e/defaults/main.test.bicep b/avm/res/machine-learning-services/workspace/tests/e2e/defaults/main.test.bicep index 6641997985..94625f8a3d 100644 --- a/avm/res/machine-learning-services/workspace/tests/e2e/defaults/main.test.bicep +++ b/avm/res/machine-learning-services/workspace/tests/e2e/defaults/main.test.bicep @@ -47,18 +47,20 @@ 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 - associatedApplicationInsightsResourceId: nestedDependencies.outputs.applicationInsightsResourceId - associatedKeyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - associatedStorageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId - sku: 'Basic' +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 + associatedApplicationInsightsResourceId: nestedDependencies.outputs.applicationInsightsResourceId + associatedKeyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + associatedStorageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + sku: 'Basic' + } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/machine-learning-services/workspace/tests/e2e/encr/dependencies.bicep b/avm/res/machine-learning-services/workspace/tests/e2e/encr/dependencies.bicep index ff1e354c49..4e41990054 100644 --- a/avm/res/machine-learning-services/workspace/tests/e2e/encr/dependencies.bicep +++ b/avm/res/machine-learning-services/workspace/tests/e2e/encr/dependencies.bicep @@ -51,7 +51,10 @@ resource keyVaultServicePermissions 'Microsoft.Authorization/roleAssignments@202 scope: keyVault properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b24988ac-6180-42a0-ab88-20f7382dd24c' + ) // Contributor principalType: 'ServicePrincipal' } } @@ -60,7 +63,10 @@ resource keyVaultDataPermissions 'Microsoft.Authorization/roleAssignments@2022-0 scope: keyVault::key properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '12338af0-0e69-4776-bea7-57ae8d297424' + ) // Key Vault Crypto User principalType: 'ServicePrincipal' } } diff --git a/avm/res/machine-learning-services/workspace/tests/e2e/encr/main.test.bicep b/avm/res/machine-learning-services/workspace/tests/e2e/encr/main.test.bicep index d133c23c22..909437d5c9 100644 --- a/avm/res/machine-learning-services/workspace/tests/e2e/encr/main.test.bicep +++ b/avm/res/machine-learning-services/workspace/tests/e2e/encr/main.test.bicep @@ -52,30 +52,32 @@ 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 - associatedApplicationInsightsResourceId: nestedDependencies.outputs.applicationInsightsResourceId - associatedKeyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - associatedStorageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId - sku: 'Basic' - customerManagedKey: { - keyName: nestedDependencies.outputs.keyVaultEncryptionKeyName - keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - userAssignedIdentityResourceId: nestedDependencies.outputs.managedIdentityResourceId - } - primaryUserAssignedIdentity: nestedDependencies.outputs.managedIdentityResourceId - managedIdentities: { - systemAssigned: false - 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 + associatedApplicationInsightsResourceId: nestedDependencies.outputs.applicationInsightsResourceId + associatedKeyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + associatedStorageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + sku: 'Basic' + customerManagedKey: { + keyName: nestedDependencies.outputs.keyVaultEncryptionKeyName + keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + userAssignedIdentityResourceId: nestedDependencies.outputs.managedIdentityResourceId + } + primaryUserAssignedIdentity: nestedDependencies.outputs.managedIdentityResourceId + managedIdentities: { + systemAssigned: false + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/machine-learning-services/workspace/tests/e2e/max/dependencies.bicep b/avm/res/machine-learning-services/workspace/tests/e2e/max/dependencies.bicep index 4f7b46494d..2002a08799 100644 --- a/avm/res/machine-learning-services/workspace/tests/e2e/max/dependencies.bicep +++ b/avm/res/machine-learning-services/workspace/tests/e2e/max/dependencies.bicep @@ -66,7 +66,10 @@ resource keyVaultServicePermissions 'Microsoft.Authorization/roleAssignments@202 scope: keyVault properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b24988ac-6180-42a0-ab88-20f7382dd24c' + ) // Contributor principalType: 'ServicePrincipal' } } @@ -75,7 +78,10 @@ resource keyVaultDataPermissions 'Microsoft.Authorization/roleAssignments@2022-0 scope: keyVault properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483') // Key Vault Administrator + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '00482a5a-887f-4fb3-b363-3b7fe8e74483' + ) // Key Vault Administrator principalType: 'ServicePrincipal' } } diff --git a/avm/res/machine-learning-services/workspace/tests/e2e/max/main.test.bicep b/avm/res/machine-learning-services/workspace/tests/e2e/max/main.test.bicep index 6cfc6403a7..de85acc87e 100644 --- a/avm/res/machine-learning-services/workspace/tests/e2e/max/main.test.bicep +++ b/avm/res/machine-learning-services/workspace/tests/e2e/max/main.test.bicep @@ -63,118 +63,123 @@ 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 - associatedApplicationInsightsResourceId: nestedDependencies.outputs.applicationInsightsResourceId - associatedKeyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - associatedStorageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId - sku: 'Premium' - computes: [ - { - computeLocation: resourceLocation - computeType: 'AmlCompute' - description: 'Default CPU Cluster' - disableLocalAuth: false - location: resourceLocation - name: 'DefaultCPU' - properties: { - enableNodePublicIp: true - isolatedNetwork: false - osType: 'Linux' - remoteLoginPortPublicAccess: 'Disabled' - scaleSettings: { - maxNodeCount: 3 - minNodeCount: 0 - nodeIdleTimeBeforeScaleDown: 'PT5M' +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 + associatedApplicationInsightsResourceId: nestedDependencies.outputs.applicationInsightsResourceId + associatedKeyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + associatedStorageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + sku: 'Premium' + computes: [ + { + computeLocation: resourceLocation + computeType: 'AmlCompute' + description: 'Default CPU Cluster' + disableLocalAuth: false + location: resourceLocation + name: 'DefaultCPU' + properties: { + enableNodePublicIp: true + isolatedNetwork: false + osType: 'Linux' + remoteLoginPortPublicAccess: 'Disabled' + scaleSettings: { + maxNodeCount: 3 + minNodeCount: 0 + nodeIdleTimeBeforeScaleDown: 'PT5M' + } + vmPriority: 'Dedicated' + vmSize: 'STANDARD_DS11_V2' + } + sku: 'Basic' + managedIdentities: { + systemAssigned: false + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] } - vmPriority: 'Dedicated' - vmSize: 'STANDARD_DS11_V2' } - sku: 'Basic' - managedIdentities: { - systemAssigned: false - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId + ] + description: 'The cake is a lie.' + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } + ] + discoveryUrl: 'http://example.com' + imageBuildCompute: 'testcompute' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - description: 'The cake is a lie.' - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' + primaryUserAssignedIdentity: nestedDependencies.outputs.managedIdentityResourceId + privateEndpoints: [ + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - discoveryUrl: 'http://example.com' - imageBuildCompute: 'testcompute' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - primaryUserAssignedIdentity: nestedDependencies.outputs.managedIdentityResourceId - privateEndpoints: [ - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } - } - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + } + ] + 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' + } + ] + managedIdentities: { + systemAssigned: false + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId ] } - ] - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - ] - managedIdentities: { - systemAssigned: false - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/machine-learning-services/workspace/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/machine-learning-services/workspace/tests/e2e/waf-aligned/dependencies.bicep index 4f7b46494d..2002a08799 100644 --- a/avm/res/machine-learning-services/workspace/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/machine-learning-services/workspace/tests/e2e/waf-aligned/dependencies.bicep @@ -66,7 +66,10 @@ resource keyVaultServicePermissions 'Microsoft.Authorization/roleAssignments@202 scope: keyVault properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b24988ac-6180-42a0-ab88-20f7382dd24c' + ) // Contributor principalType: 'ServicePrincipal' } } @@ -75,7 +78,10 @@ resource keyVaultDataPermissions 'Microsoft.Authorization/roleAssignments@2022-0 scope: keyVault properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483') // Key Vault Administrator + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '00482a5a-887f-4fb3-b363-3b7fe8e74483' + ) // Key Vault Administrator principalType: 'ServicePrincipal' } } diff --git a/avm/res/machine-learning-services/workspace/tests/e2e/waf-aligned/main.test.bicep b/avm/res/machine-learning-services/workspace/tests/e2e/waf-aligned/main.test.bicep index 4a4ee2aafb..8835d7b037 100644 --- a/avm/res/machine-learning-services/workspace/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/machine-learning-services/workspace/tests/e2e/waf-aligned/main.test.bicep @@ -63,45 +63,47 @@ 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 - associatedApplicationInsightsResourceId: nestedDependencies.outputs.applicationInsightsResourceId - associatedKeyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - associatedStorageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId - sku: 'Standard' - diagnosticSettings: [ - { - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - privateEndpoints: [ - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +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 + associatedApplicationInsightsResourceId: nestedDependencies.outputs.applicationInsightsResourceId + associatedKeyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + associatedStorageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + sku: 'Standard' + diagnosticSettings: [ + { + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + privateEndpoints: [ + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/maintenance/maintenance-configuration/main.bicep b/avm/res/maintenance/maintenance-configuration/main.bicep index 0bd0fd9c37..729f65882d 100644 --- a/avm/res/maintenance/maintenance-configuration/main.bicep +++ b/avm/res/maintenance/maintenance-configuration/main.bicep @@ -63,28 +63,38 @@ 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'Scheduled Patching Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cd08ab90-6b14-449c-ad9a-8f8e549482c6') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' + ) + 'Scheduled Patching Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'cd08ab90-6b14-449c-ad9a-8f8e549482c6' + ) + 'User Access Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.maintenance-maintenanceconfiguration.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.maintenance-maintenanceconfiguration.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource maintenanceConfiguration 'Microsoft.Maintenance/maintenanceConfigurations@2023-04-01' = { location: location @@ -100,28 +110,37 @@ resource maintenanceConfiguration 'Microsoft.Maintenance/maintenanceConfiguratio } } -resource maintenanceConfiguration_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.' +resource maintenanceConfiguration_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: maintenanceConfiguration } - scope: maintenanceConfiguration -} -resource maintenanceConfiguration_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(maintenanceConfiguration.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource maintenanceConfiguration_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(maintenanceConfiguration.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: maintenanceConfiguration } - scope: maintenanceConfiguration -}] +] // =========== // // Outputs // diff --git a/avm/res/maintenance/maintenance-configuration/main.json b/avm/res/maintenance/maintenance-configuration/main.json index f06917ab55..f2d9aa1a6f 100644 --- a/avm/res/maintenance/maintenance-configuration/main.json +++ b/avm/res/maintenance/maintenance-configuration/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16015110608585715401" + "version": "0.26.54.24096", + "templateHash": "1159826078324391802" }, "name": "Maintenance Configurations", "description": "This module deploys a Maintenance Configuration.", diff --git a/avm/res/maintenance/maintenance-configuration/tests/e2e/defaults/main.test.bicep b/avm/res/maintenance/maintenance-configuration/tests/e2e/defaults/main.test.bicep index 7eee9f0efe..8799ed5e45 100644 --- a/avm/res/maintenance/maintenance-configuration/tests/e2e/defaults/main.test.bicep +++ b/avm/res/maintenance/maintenance-configuration/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 +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 + } } -}] +] diff --git a/avm/res/maintenance/maintenance-configuration/tests/e2e/max/dependencies.bicep b/avm/res/maintenance/maintenance-configuration/tests/e2e/max/dependencies.bicep index a7f42aee7b..7be39e253a 100644 --- a/avm/res/maintenance/maintenance-configuration/tests/e2e/max/dependencies.bicep +++ b/avm/res/maintenance/maintenance-configuration/tests/e2e/max/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/maintenance/maintenance-configuration/tests/e2e/max/main.test.bicep b/avm/res/maintenance/maintenance-configuration/tests/e2e/max/main.test.bicep index a6c8080465..c794755eb8 100644 --- a/avm/res/maintenance/maintenance-configuration/tests/e2e/max/main.test.bicep +++ b/avm/res/maintenance/maintenance-configuration/tests/e2e/max/main.test.bicep @@ -45,66 +45,71 @@ 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 - extensionProperties: { - InGuestPatchMode: 'User' - } - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +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 + extensionProperties: { + InGuestPatchMode: 'User' } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - 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' + Role: 'DeploymentValidation' } - ] - maintenanceScope: 'InGuestPatch' - maintenanceWindow: { - duration: '03:00' - expirationDateTime: '9999-12-31 23:59:59' - recurEvery: 'Day' - startDateTime: '2022-12-31 13:00' - timeZone: 'W. Europe Standard Time' - } - namespace: '${serviceShort}ns' - visibility: 'Custom' - installPatches: { - linuxParameters: { - classificationsToInclude: null - packageNameMasksToExclude: null - packageNameMasksToInclude: null + 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' + } + ] + maintenanceScope: 'InGuestPatch' + maintenanceWindow: { + duration: '03:00' + expirationDateTime: '9999-12-31 23:59:59' + recurEvery: 'Day' + startDateTime: '2022-12-31 13:00' + timeZone: 'W. Europe Standard Time' } - rebootSetting: 'IfRequired' - windowsParameters: { - classificationsToInclude: [ - 'Critical' - 'Security' - ] - kbNumbersToExclude: null - kbNumbersToInclude: null + namespace: '${serviceShort}ns' + visibility: 'Custom' + installPatches: { + linuxParameters: { + classificationsToInclude: null + packageNameMasksToExclude: null + packageNameMasksToInclude: null + } + rebootSetting: 'IfRequired' + windowsParameters: { + classificationsToInclude: [ + 'Critical' + 'Security' + ] + kbNumbersToExclude: null + kbNumbersToInclude: null + } } } } -}] +] diff --git a/avm/res/maintenance/maintenance-configuration/tests/e2e/waf-aligned/main.test.bicep b/avm/res/maintenance/maintenance-configuration/tests/e2e/waf-aligned/main.test.bicep index 2eb217f971..a7ed09b649 100644 --- a/avm/res/maintenance/maintenance-configuration/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/maintenance/maintenance-configuration/tests/e2e/waf-aligned/main.test.bicep @@ -36,45 +36,47 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 - extensionProperties: { - InGuestPatchMode: 'User' - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - maintenanceScope: 'InGuestPatch' - maintenanceWindow: { - duration: '03:00' - expirationDateTime: '9999-12-31 23:59:59' - recurEvery: 'Day' - startDateTime: '2022-12-31 13:00' - timeZone: 'W. Europe Standard Time' - } - namespace: '${serviceShort}ns' - visibility: 'Custom' - installPatches: { - linuxParameters: { - classificationsToInclude: null - packageNameMasksToExclude: null - packageNameMasksToInclude: null +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 + extensionProperties: { + InGuestPatchMode: 'User' + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + maintenanceScope: 'InGuestPatch' + maintenanceWindow: { + duration: '03:00' + expirationDateTime: '9999-12-31 23:59:59' + recurEvery: 'Day' + startDateTime: '2022-12-31 13:00' + timeZone: 'W. Europe Standard Time' } - rebootSetting: 'IfRequired' - windowsParameters: { - classificationsToInclude: [ - 'Critical' - 'Security' - ] - kbNumbersToExclude: null - kbNumbersToInclude: null + namespace: '${serviceShort}ns' + visibility: 'Custom' + installPatches: { + linuxParameters: { + classificationsToInclude: null + packageNameMasksToExclude: null + packageNameMasksToInclude: null + } + rebootSetting: 'IfRequired' + windowsParameters: { + classificationsToInclude: [ + 'Critical' + 'Security' + ] + kbNumbersToExclude: null + kbNumbersToInclude: null + } } } } -}] +] diff --git a/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/main.json b/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/main.json index 41b27ff161..ea926bbb96 100644 --- a/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/main.json +++ b/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "15826270550299120709" + "version": "0.26.54.24096", + "templateHash": "4317497001099502136" }, "name": "User Assigned Identity Federated Identity Credential", "description": "This module deploys a User Assigned Identity Federated Identity Credential.", diff --git a/avm/res/managed-identity/user-assigned-identity/main.bicep b/avm/res/managed-identity/user-assigned-identity/main.bicep index 71ef19b973..a5ebb6e4cd 100644 --- a/avm/res/managed-identity/user-assigned-identity/main.bicep +++ b/avm/res/managed-identity/user-assigned-identity/main.bicep @@ -25,31 +25,44 @@ param enableTelemetry bool = true var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Managed Identity Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59') - 'Managed Identity Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830') + 'Managed Identity Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59' + ) + 'Managed Identity Operator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f1a07417-d97a-45cb-824c-7a7467783830' + ) 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') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.managedidentity-userassignedidentity.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.managedidentity-userassignedidentity.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource userAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { name: name @@ -57,39 +70,50 @@ resource userAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@ tags: tags } -resource userAssignedIdentity_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.' +resource userAssignedIdentity_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: userAssignedIdentity } - scope: userAssignedIdentity -} -module userAssignedIdentity_federatedIdentityCredentials 'federated-identity-credential/main.bicep' = [for (federatedIdentityCredential, index) in (federatedIdentityCredentials ?? []): { - name: '${uniqueString(deployment().name, location)}-UserMSI-FederatedIdentityCredential-${index}' - params: { - name: federatedIdentityCredential.name - userAssignedIdentityName: userAssignedIdentity.name - audiences: federatedIdentityCredential.audiences - issuer: federatedIdentityCredential.issuer - subject: federatedIdentityCredential.subject +module userAssignedIdentity_federatedIdentityCredentials 'federated-identity-credential/main.bicep' = [ + for (federatedIdentityCredential, index) in (federatedIdentityCredentials ?? []): { + name: '${uniqueString(deployment().name, location)}-UserMSI-FederatedIdentityCredential-${index}' + params: { + name: federatedIdentityCredential.name + userAssignedIdentityName: userAssignedIdentity.name + audiences: federatedIdentityCredential.audiences + issuer: federatedIdentityCredential.issuer + subject: federatedIdentityCredential.subject + } } -}] - -resource userAssignedIdentity_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(userAssignedIdentity.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +] + +resource userAssignedIdentity_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(userAssignedIdentity.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: userAssignedIdentity } - scope: userAssignedIdentity -}] +] @description('The name of the user assigned identity.') output name string = userAssignedIdentity.name diff --git a/avm/res/managed-identity/user-assigned-identity/main.json b/avm/res/managed-identity/user-assigned-identity/main.json index 750eb2c5d0..7d006d7143 100644 --- a/avm/res/managed-identity/user-assigned-identity/main.json +++ b/avm/res/managed-identity/user-assigned-identity/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11532993654681133775" + "version": "0.26.54.24096", + "templateHash": "8193140269981034553" }, "name": "User Assigned Identities", "description": "This module deploys a User Assigned Identity.", @@ -299,8 +299,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "15826270550299120709" + "version": "0.26.54.24096", + "templateHash": "4317497001099502136" }, "name": "User Assigned Identity Federated Identity Credential", "description": "This module deploys a User Assigned Identity Federated Identity Credential.", diff --git a/avm/res/managed-identity/user-assigned-identity/tests/e2e/defaults/main.test.bicep b/avm/res/managed-identity/user-assigned-identity/tests/e2e/defaults/main.test.bicep index 97d58c24d0..627b394869 100644 --- a/avm/res/managed-identity/user-assigned-identity/tests/e2e/defaults/main.test.bicep +++ b/avm/res/managed-identity/user-assigned-identity/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 +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 + } } -}] +] diff --git a/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/dependencies.bicep b/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/dependencies.bicep index a7f42aee7b..7be39e253a 100644 --- a/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/dependencies.bicep +++ b/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/main.test.bicep b/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/main.test.bicep index 17ce769ad4..3d917bafd1 100644 --- a/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/main.test.bicep +++ b/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/main.test.bicep @@ -49,47 +49,52 @@ 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: enforcedLocation - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - federatedIdentityCredentials: [ - { - name: 'test-fed-cred-${serviceShort}-001' - audiences: [ - 'api://AzureADTokenExchange' - ] - issuer: 'https://contoso.com/${subscription().tenantId}/${guid(deployment().name)}/' - subject: 'system:serviceaccount:default:workload-identity-sa' - } - ] - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +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: enforcedLocation + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + federatedIdentityCredentials: [ + { + name: 'test-fed-cred-${serviceShort}-001' + audiences: [ + 'api://AzureADTokenExchange' + ] + issuer: 'https://contoso.com/${subscription().tenantId}/${guid(deployment().name)}/' + subject: 'system:serviceaccount:default:workload-identity-sa' + } + ] + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/dependencies.bicep index a7f42aee7b..7be39e253a 100644 --- a/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/main.test.bicep b/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/main.test.bicep index 4d34dd01e5..2131970f5f 100644 --- a/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/main.test.bicep @@ -40,30 +40,32 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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: enforcedLocation - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - federatedIdentityCredentials: [ - { - name: 'test-fed-cred-${serviceShort}-001' - audiences: [ - 'api://AzureADTokenExchange' - ] - issuer: 'https://contoso.com/${subscription().tenantId}/${guid(deployment().name)}/' - subject: 'system:serviceaccount:default:workload-identity-sa' +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: enforcedLocation + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + federatedIdentityCredentials: [ + { + name: 'test-fed-cred-${serviceShort}-001' + audiences: [ + 'api://AzureADTokenExchange' + ] + issuer: 'https://contoso.com/${subscription().tenantId}/${guid(deployment().name)}/' + subject: 'system:serviceaccount:default:workload-identity-sa' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/management/management-group/main.bicep b/avm/res/management/management-group/main.bicep index 589fe375fa..563e3314f8 100644 --- a/avm/res/management/management-group/main.bicep +++ b/avm/res/management/management-group/main.bicep @@ -23,24 +23,25 @@ param location string = deployment().location @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.management-managementgroup.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - location: location - 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' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.management-managementgroup.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + location: location + 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' + } } } } } -} resource parentManagementGroup 'Microsoft.Management/managementGroups@2021-04-01' existing = { name: parentId @@ -52,11 +53,13 @@ resource managementGroup 'Microsoft.Management/managementGroups@2021-04-01' = { scope: tenant() properties: { displayName: displayName - details: !empty(parentId) ? { - parent: { - id: parentManagementGroup.id - } - } : null + details: !empty(parentId) + ? { + parent: { + id: parentManagementGroup.id + } + } + : null } } diff --git a/avm/res/management/management-group/main.json b/avm/res/management/management-group/main.json index 7fe3ed1d62..7457babe82 100644 --- a/avm/res/management/management-group/main.json +++ b/avm/res/management/management-group/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14104914545746658709" + "version": "0.26.54.24096", + "templateHash": "4075622511282134710" }, "name": "Management Groups", "description": "This template will prepare the management group structure based on the provided parameter.\n\nThis module has some known **limitations**:\n- It's not possible to change the display name of the root management group (the one that has the tenant GUID as ID)\n- It can't manage the Root (/) management group", diff --git a/avm/res/management/management-group/tests/e2e/defaults/main.test.bicep b/avm/res/management/management-group/tests/e2e/defaults/main.test.bicep index cd24a798ff..f2c6516d82 100644 --- a/avm/res/management/management-group/tests/e2e/defaults/main.test.bicep +++ b/avm/res/management/management-group/tests/e2e/defaults/main.test.bicep @@ -21,10 +21,12 @@ param namePrefix string = '#_namePrefix_#' // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - name: '${uniqueString(deployment().name)}-test-${serviceShort}-${iteration}' - params: { - name: '${namePrefix}${serviceShort}001' - location: resourceLocation +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + name: '${uniqueString(deployment().name)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: resourceLocation + } } -}] +] diff --git a/avm/res/management/management-group/tests/e2e/max/main.test.bicep b/avm/res/management/management-group/tests/e2e/max/main.test.bicep index 38ef9faf72..c2ca358b8d 100644 --- a/avm/res/management/management-group/tests/e2e/max/main.test.bicep +++ b/avm/res/management/management-group/tests/e2e/max/main.test.bicep @@ -21,12 +21,14 @@ param namePrefix string = '#_namePrefix_#' // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - name: '${uniqueString(deployment().name)}-test-${serviceShort}-${iteration}' - params: { - name: '${namePrefix}${serviceShort}001' - location: resourceLocation - displayName: 'Test MG' - parentId: last(split(managementGroup().id, '/')) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + name: '${uniqueString(deployment().name)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: resourceLocation + displayName: 'Test MG' + parentId: last(split(managementGroup().id, '/')) + } } -}] +] diff --git a/avm/res/management/management-group/tests/e2e/waf-aligned/main.test.bicep b/avm/res/management/management-group/tests/e2e/waf-aligned/main.test.bicep index a27ae728fa..aed91e35e6 100644 --- a/avm/res/management/management-group/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/management/management-group/tests/e2e/waf-aligned/main.test.bicep @@ -21,12 +21,14 @@ param namePrefix string = '#_namePrefix_#' // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - name: '${uniqueString(deployment().name)}-test-${serviceShort}-${iteration}' - params: { - name: '${namePrefix}${serviceShort}001' - location: resourceLocation - displayName: 'Test MG' - parentId: last(split(managementGroup().id, '/')) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + name: '${uniqueString(deployment().name)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: resourceLocation + displayName: 'Test MG' + parentId: last(split(managementGroup().id, '/')) + } } -}] +] diff --git a/avm/res/network/application-security-group/main.bicep b/avm/res/network/application-security-group/main.bicep index 9ba811ed6c..f514b81a70 100644 --- a/avm/res/network/application-security-group/main.bicep +++ b/avm/res/network/application-security-group/main.bicep @@ -24,27 +24,34 @@ 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-applicationsecuritygroup.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-applicationsecuritygroup.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource applicationSecurityGroup 'Microsoft.Network/applicationSecurityGroups@2023-04-01' = { name: name @@ -53,28 +60,37 @@ resource applicationSecurityGroup 'Microsoft.Network/applicationSecurityGroups@2 properties: {} } -resource applicationSecurityGroup_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.' +resource applicationSecurityGroup_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: applicationSecurityGroup } - scope: applicationSecurityGroup -} -resource applicationSecurityGroup_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(applicationSecurityGroup.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource applicationSecurityGroup_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(applicationSecurityGroup.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: applicationSecurityGroup } - scope: applicationSecurityGroup -}] +] @description('The resource group the application security group was deployed into.') output resourceGroupName string = resourceGroup().name diff --git a/avm/res/network/application-security-group/main.json b/avm/res/network/application-security-group/main.json index 02317ce977..60d6778939 100644 --- a/avm/res/network/application-security-group/main.json +++ b/avm/res/network/application-security-group/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "18328102101906578940" + "version": "0.26.54.24096", + "templateHash": "8902169234314141631" }, "name": "Application Security Groups (ASG)", "description": "This module deploys an Application Security Group (ASG).", diff --git a/avm/res/network/application-security-group/tests/e2e/defaults/main.test.bicep b/avm/res/network/application-security-group/tests/e2e/defaults/main.test.bicep index 3805501d29..1a8be9a7d2 100644 --- a/avm/res/network/application-security-group/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/application-security-group/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 +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 + } } -}] +] diff --git a/avm/res/network/application-security-group/tests/e2e/max/dependencies.bicep b/avm/res/network/application-security-group/tests/e2e/max/dependencies.bicep index a7f42aee7b..7be39e253a 100644 --- a/avm/res/network/application-security-group/tests/e2e/max/dependencies.bicep +++ b/avm/res/network/application-security-group/tests/e2e/max/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/network/application-security-group/tests/e2e/max/main.test.bicep b/avm/res/network/application-security-group/tests/e2e/max/main.test.bicep index ad4f14a855..773b0b4e2f 100644 --- a/avm/res/network/application-security-group/tests/e2e/max/main.test.bicep +++ b/avm/res/network/application-security-group/tests/e2e/max/main.test.bicep @@ -45,37 +45,42 @@ 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 - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +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 + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/network/application-security-group/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/application-security-group/tests/e2e/waf-aligned/main.test.bicep index 9743d1fe3b..ba74bf9828 100644 --- a/avm/res/network/application-security-group/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/application-security-group/tests/e2e/waf-aligned/main.test.bicep @@ -36,20 +36,22 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +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 + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } } -}] +] diff --git a/avm/res/network/azure-firewall/main.bicep b/avm/res/network/azure-firewall/main.bicep index f0edf1142c..08f4af0cc2 100644 --- a/avm/res/network/azure-firewall/main.bicep +++ b/avm/res/network/azure-firewall/main.bicep @@ -94,29 +94,41 @@ var isCreateDefaultManagementIP = empty(managementIPResourceID) && requiresManag // 2. Use new Public IP created in this module // 3. Do not use a Public IP if publicIPAddressObject is empty -var additionalPublicIpConfigurationsVar = [for ipConfiguration in additionalPublicIpConfigurations: { - name: ipConfiguration.name - properties: { - publicIPAddress: contains(ipConfiguration, 'publicIPAddressResourceId') ? { - id: ipConfiguration.publicIPAddressResourceId - } : null +var additionalPublicIpConfigurationsVar = [ + for ipConfiguration in additionalPublicIpConfigurations: { + name: ipConfiguration.name + properties: { + publicIPAddress: contains(ipConfiguration, 'publicIPAddressResourceId') + ? { + id: ipConfiguration.publicIPAddressResourceId + } + : null + } } -}] -var ipConfigurations = concat([ +] +var ipConfigurations = concat( + [ { name: !empty(publicIPResourceID) ? last(split(publicIPResourceID, '/')) : publicIPAddress.outputs.name - properties: union({ + properties: union( + { subnet: { id: '${virtualNetworkResourceId}/subnets/AzureFirewallSubnet' // The subnet name must be AzureFirewallSubnet } - }, (!empty(publicIPResourceID) || !empty(publicIPAddressObject)) ? { - //Use existing Public IP, new Public IP created in this module, or none if neither - publicIPAddress: { - id: !empty(publicIPResourceID) ? publicIPResourceID : publicIPAddress.outputs.resourceId - } - } : {}) + }, + (!empty(publicIPResourceID) || !empty(publicIPAddressObject)) + ? { + //Use existing Public IP, new Public IP created in this module, or none if neither + publicIPAddress: { + id: !empty(publicIPResourceID) ? publicIPResourceID : publicIPAddress.outputs.resourceId + } + } + : {} + ) } - ], additionalPublicIpConfigurationsVar) + ], + additionalPublicIpConfigurationsVar +) // ---------------------------------------------------------------------------- // Prep managementIPConfiguration object for different uses cases: @@ -125,16 +137,21 @@ var ipConfigurations = concat([ var managementIPConfiguration = { name: !empty(managementIPResourceID) ? last(split(managementIPResourceID, '/')) : managementIPAddress.outputs.name - properties: union({ + properties: union( + { subnet: { id: '${virtualNetworkResourceId}/subnets/AzureFirewallManagementSubnet' // The subnet name must be AzureFirewallManagementSubnet for a 'Basic' SKU tier firewall } - }, (!empty(publicIPResourceID) || !empty(managementIPAddressObject)) ? { - // Use existing Management Public IP, new Management Public IP created in this module, or none if neither - publicIPAddress: { - id: !empty(managementIPResourceID) ? managementIPResourceID : managementIPAddress.outputs.resourceId - } - } : {}) + }, + (!empty(publicIPResourceID) || !empty(managementIPAddressObject)) + ? { + // Use existing Management Public IP, new Management Public IP created in this module, or none if neither + publicIPAddress: { + id: !empty(managementIPResourceID) ? managementIPResourceID : managementIPAddress.outputs.resourceId + } + } + : {} + ) } // ---------------------------------------------------------------------------- @@ -142,143 +159,205 @@ 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-azurefirewall.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-azurefirewall.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} -module publicIPAddress 'br/public:avm/res/network/public-ip-address:0.2.1' = if (empty(publicIPResourceID) && azureSkuName == 'AZFW_VNet') { - name: '${uniqueString(deployment().name, location)}-Firewall-PIP' - params: { - name: publicIPAddressObject.name - publicIpPrefixResourceId: contains(publicIPAddressObject, 'publicIPPrefixResourceId') ? (!(empty(publicIPAddressObject.publicIPPrefixResourceId)) ? publicIPAddressObject.publicIPPrefixResourceId : '') : '' - publicIPAllocationMethod: contains(publicIPAddressObject, 'publicIPAllocationMethod') ? (!(empty(publicIPAddressObject.publicIPAllocationMethod)) ? publicIPAddressObject.publicIPAllocationMethod : 'Static') : 'Static' - skuName: contains(publicIPAddressObject, 'skuName') ? (!(empty(publicIPAddressObject.skuName)) ? publicIPAddressObject.skuName : 'Standard') : 'Standard' - skuTier: contains(publicIPAddressObject, 'skuTier') ? (!(empty(publicIPAddressObject.skuTier)) ? publicIPAddressObject.skuTier : 'Regional') : 'Regional' - roleAssignments: contains(publicIPAddressObject, 'roleAssignments') ? (!empty(publicIPAddressObject.roleAssignments) ? publicIPAddressObject.roleAssignments : []) : [] - diagnosticSettings: publicIPAddressObject.?diagnosticSettings - location: location - lock: lock - tags: publicIPAddressObject.?tags ?? tags - zones: zones - enableTelemetry: publicIPAddressObject.?enableTelemetry ?? enableTelemetry +module publicIPAddress 'br/public:avm/res/network/public-ip-address:0.2.1' = + if (empty(publicIPResourceID) && azureSkuName == 'AZFW_VNet') { + name: '${uniqueString(deployment().name, location)}-Firewall-PIP' + params: { + name: publicIPAddressObject.name + publicIpPrefixResourceId: contains(publicIPAddressObject, 'publicIPPrefixResourceId') + ? (!(empty(publicIPAddressObject.publicIPPrefixResourceId)) + ? publicIPAddressObject.publicIPPrefixResourceId + : '') + : '' + publicIPAllocationMethod: contains(publicIPAddressObject, 'publicIPAllocationMethod') + ? (!(empty(publicIPAddressObject.publicIPAllocationMethod)) + ? publicIPAddressObject.publicIPAllocationMethod + : 'Static') + : 'Static' + skuName: contains(publicIPAddressObject, 'skuName') + ? (!(empty(publicIPAddressObject.skuName)) ? publicIPAddressObject.skuName : 'Standard') + : 'Standard' + skuTier: contains(publicIPAddressObject, 'skuTier') + ? (!(empty(publicIPAddressObject.skuTier)) ? publicIPAddressObject.skuTier : 'Regional') + : 'Regional' + roleAssignments: contains(publicIPAddressObject, 'roleAssignments') + ? (!empty(publicIPAddressObject.roleAssignments) ? publicIPAddressObject.roleAssignments : []) + : [] + diagnosticSettings: publicIPAddressObject.?diagnosticSettings + location: location + lock: lock + tags: publicIPAddressObject.?tags ?? tags + zones: zones + enableTelemetry: publicIPAddressObject.?enableTelemetry ?? enableTelemetry + } } -} // create a Management Public IP address if one is not provided and the flag is true -module managementIPAddress 'br/public:avm/res/network/public-ip-address:0.2.1' = if (isCreateDefaultManagementIP && azureSkuName == 'AZFW_VNet') { - name: '${uniqueString(deployment().name, location)}-Firewall-MIP' - params: { - name: contains(managementIPAddressObject, 'name') ? (!(empty(managementIPAddressObject.name)) ? managementIPAddressObject.name : '${name}-mip') : '${name}-mip' - publicIpPrefixResourceId: contains(managementIPAddressObject, 'managementIPPrefixResourceId') ? (!(empty(managementIPAddressObject.publicIPPrefixResourceId)) ? managementIPAddressObject.publicIPPrefixResourceId : '') : '' - publicIPAllocationMethod: contains(managementIPAddressObject, 'managementIPAllocationMethod') ? (!(empty(managementIPAddressObject.publicIPAllocationMethod)) ? managementIPAddressObject.publicIPAllocationMethod : 'Static') : 'Static' - skuName: contains(managementIPAddressObject, 'skuName') ? (!(empty(managementIPAddressObject.skuName)) ? managementIPAddressObject.skuName : 'Standard') : 'Standard' - skuTier: contains(managementIPAddressObject, 'skuTier') ? (!(empty(managementIPAddressObject.skuTier)) ? managementIPAddressObject.skuTier : 'Regional') : 'Regional' - roleAssignments: contains(managementIPAddressObject, 'roleAssignments') ? (!empty(managementIPAddressObject.roleAssignments) ? managementIPAddressObject.roleAssignments : []) : [] - diagnosticSettings: managementIPAddressObject.?diagnosticSettings - location: location - tags: managementIPAddressObject.?tags ?? tags - zones: zones - enableTelemetry: managementIPAddressObject.?enableTelemetry ?? enableTelemetry +module managementIPAddress 'br/public:avm/res/network/public-ip-address:0.2.1' = + if (isCreateDefaultManagementIP && azureSkuName == 'AZFW_VNet') { + name: '${uniqueString(deployment().name, location)}-Firewall-MIP' + params: { + name: contains(managementIPAddressObject, 'name') + ? (!(empty(managementIPAddressObject.name)) ? managementIPAddressObject.name : '${name}-mip') + : '${name}-mip' + publicIpPrefixResourceId: contains(managementIPAddressObject, 'managementIPPrefixResourceId') + ? (!(empty(managementIPAddressObject.publicIPPrefixResourceId)) + ? managementIPAddressObject.publicIPPrefixResourceId + : '') + : '' + publicIPAllocationMethod: contains(managementIPAddressObject, 'managementIPAllocationMethod') + ? (!(empty(managementIPAddressObject.publicIPAllocationMethod)) + ? managementIPAddressObject.publicIPAllocationMethod + : 'Static') + : 'Static' + skuName: contains(managementIPAddressObject, 'skuName') + ? (!(empty(managementIPAddressObject.skuName)) ? managementIPAddressObject.skuName : 'Standard') + : 'Standard' + skuTier: contains(managementIPAddressObject, 'skuTier') + ? (!(empty(managementIPAddressObject.skuTier)) ? managementIPAddressObject.skuTier : 'Regional') + : 'Regional' + roleAssignments: contains(managementIPAddressObject, 'roleAssignments') + ? (!empty(managementIPAddressObject.roleAssignments) ? managementIPAddressObject.roleAssignments : []) + : [] + diagnosticSettings: managementIPAddressObject.?diagnosticSettings + location: location + tags: managementIPAddressObject.?tags ?? tags + zones: zones + enableTelemetry: managementIPAddressObject.?enableTelemetry ?? enableTelemetry + } } -} resource azureFirewall 'Microsoft.Network/azureFirewalls@2023-04-01' = { name: name location: location zones: length(zones) == 0 ? null : zones tags: tags - properties: azureSkuName == 'AZFW_VNet' ? { - threatIntelMode: threatIntelMode - firewallPolicy: !empty(firewallPolicyId) ? { - id: firewallPolicyId - } : null - ipConfigurations: ipConfigurations - managementIpConfiguration: requiresManagementIp ? managementIPConfiguration : null - sku: { - name: azureSkuName - tier: azureSkuTier - } - applicationRuleCollections: applicationRuleCollections - natRuleCollections: natRuleCollections - networkRuleCollections: networkRuleCollections - } : { - firewallPolicy: !empty(firewallPolicyId) ? { - id: firewallPolicyId - } : null - sku: { - name: azureSkuName - tier: azureSkuTier - } - hubIPAddresses: !empty(hubIPAddresses) ? hubIPAddresses : null - virtualHub: !empty(virtualHubId) ? { - id: virtualHubId - } : null - } + properties: azureSkuName == 'AZFW_VNet' + ? { + threatIntelMode: threatIntelMode + firewallPolicy: !empty(firewallPolicyId) + ? { + id: firewallPolicyId + } + : null + ipConfigurations: ipConfigurations + managementIpConfiguration: requiresManagementIp ? managementIPConfiguration : null + sku: { + name: azureSkuName + tier: azureSkuTier + } + applicationRuleCollections: applicationRuleCollections + natRuleCollections: natRuleCollections + networkRuleCollections: networkRuleCollections + } + : { + firewallPolicy: !empty(firewallPolicyId) + ? { + id: firewallPolicyId + } + : null + sku: { + name: azureSkuName + tier: azureSkuTier + } + hubIPAddresses: !empty(hubIPAddresses) ? hubIPAddresses : null + virtualHub: !empty(virtualHubId) + ? { + id: virtualHubId + } + : null + } } -resource azureFirewall_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.' +resource azureFirewall_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: azureFirewall } - scope: azureFirewall -} -resource azureFirewall_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource azureFirewall_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: azureFirewall } - scope: azureFirewall -}] - -resource azureFirewall_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(azureFirewall.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +] + +resource azureFirewall_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(azureFirewall.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: azureFirewall } - scope: azureFirewall -}] +] @description('The resource ID of the Azure Firewall.') output resourceId string = azureFirewall.id @@ -290,10 +369,14 @@ output name string = azureFirewall.name output resourceGroupName string = resourceGroup().name @description('The private IP of the Azure firewall.') -output privateIp string = contains(azureFirewall.properties, 'ipConfigurations') ? azureFirewall.properties.ipConfigurations[0].properties.privateIPAddress : '' +output privateIp string = contains(azureFirewall.properties, 'ipConfigurations') + ? azureFirewall.properties.ipConfigurations[0].properties.privateIPAddress + : '' @description('The Public IP configuration object for the Azure Firewall Subnet.') -output ipConfAzureFirewallSubnet object = contains(azureFirewall.properties, 'ipConfigurations') ? azureFirewall.properties.ipConfigurations[0] : {} +output ipConfAzureFirewallSubnet object = contains(azureFirewall.properties, 'ipConfigurations') + ? azureFirewall.properties.ipConfigurations[0] + : {} @description('List of Application Rule Collections.') output applicationRuleCollections array = applicationRuleCollections diff --git a/avm/res/network/azure-firewall/main.json b/avm/res/network/azure-firewall/main.json index 27aaafd57d..b38f878a9d 100644 --- a/avm/res/network/azure-firewall/main.json +++ b/avm/res/network/azure-firewall/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4205211650529288648" + "version": "0.26.54.24096", + "templateHash": "1527004517287633679" }, "name": "Azure Firewalls", "description": "This module deploys an Azure Firewall.", diff --git a/avm/res/network/azure-firewall/tests/e2e/addpip/main.test.bicep b/avm/res/network/azure-firewall/tests/e2e/addpip/main.test.bicep index 28f977e678..d63e79f922 100644 --- a/avm/res/network/azure-firewall/tests/e2e/addpip/main.test.bicep +++ b/avm/res/network/azure-firewall/tests/e2e/addpip/main.test.bicep @@ -47,29 +47,31 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId - additionalPublicIpConfigurations: [ - { - name: 'ipConfig01' - publicIPAddressResourceId: nestedDependencies.outputs.publicIPResourceId - } - ] - azureSkuTier: 'Basic' - managementIPAddressObject: { - publicIPAllocationMethod: 'Static' - roleAssignments: [ +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId + additionalPublicIpConfigurations: [ { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + name: 'ipConfig01' + publicIPAddressResourceId: nestedDependencies.outputs.publicIPResourceId } ] + azureSkuTier: 'Basic' + managementIPAddressObject: { + publicIPAllocationMethod: 'Static' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + } } } -}] +] diff --git a/avm/res/network/azure-firewall/tests/e2e/custompip/main.test.bicep b/avm/res/network/azure-firewall/tests/e2e/custompip/main.test.bicep index 2891ccb851..2a6977e5d9 100644 --- a/avm/res/network/azure-firewall/tests/e2e/custompip/main.test.bicep +++ b/avm/res/network/azure-firewall/tests/e2e/custompip/main.test.bicep @@ -60,40 +60,42 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId - publicIPAddressObject: { - name: 'new-${namePrefix}-pip-${serviceShort}' - publicIPAllocationMethod: 'Static' - publicIPPrefixResourceId: '' - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - ] - skuName: 'Standard' - skuTier: 'Regional' - 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: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId + publicIPAddressObject: { + name: 'new-${namePrefix}-pip-${serviceShort}' + publicIPAllocationMethod: 'Static' + publicIPPrefixResourceId: '' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + skuName: 'Standard' + skuTier: 'Regional' + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + } } } -}] +] diff --git a/avm/res/network/azure-firewall/tests/e2e/defaults/main.test.bicep b/avm/res/network/azure-firewall/tests/e2e/defaults/main.test.bicep index 623ae364cb..86ad404cac 100644 --- a/avm/res/network/azure-firewall/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/azure-firewall/tests/e2e/defaults/main.test.bicep @@ -45,12 +45,14 @@ 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' - virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId - location: resourceLocation +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId + location: resourceLocation + } } -}] +] diff --git a/avm/res/network/azure-firewall/tests/e2e/hubcommon/main.test.bicep b/avm/res/network/azure-firewall/tests/e2e/hubcommon/main.test.bicep index 91f5a5b7f4..b40d7d6f1d 100644 --- a/avm/res/network/azure-firewall/tests/e2e/hubcommon/main.test.bicep +++ b/avm/res/network/azure-firewall/tests/e2e/hubcommon/main.test.bicep @@ -47,18 +47,20 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - firewallPolicyId: nestedDependencies.outputs.firewallPolicyResourceId - virtualHubId: nestedDependencies.outputs.virtualHubResourceId - hubIPAddresses: { - publicIPs: { - count: 1 +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + firewallPolicyId: nestedDependencies.outputs.firewallPolicyResourceId + virtualHubId: nestedDependencies.outputs.virtualHubResourceId + hubIPAddresses: { + publicIPs: { + count: 1 + } } } } -}] +] diff --git a/avm/res/network/azure-firewall/tests/e2e/hubmin/main.test.bicep b/avm/res/network/azure-firewall/tests/e2e/hubmin/main.test.bicep index 25efd33efb..5787d13021 100644 --- a/avm/res/network/azure-firewall/tests/e2e/hubmin/main.test.bicep +++ b/avm/res/network/azure-firewall/tests/e2e/hubmin/main.test.bicep @@ -46,17 +46,19 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - virtualHubId: nestedDependencies.outputs.virtualHubResourceId - hubIPAddresses: { - publicIPs: { - count: 1 +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + virtualHubId: nestedDependencies.outputs.virtualHubResourceId + hubIPAddresses: { + publicIPs: { + count: 1 + } } } } -}] +] diff --git a/avm/res/network/azure-firewall/tests/e2e/max/main.test.bicep b/avm/res/network/azure-firewall/tests/e2e/max/main.test.bicep index c3c6ca138f..7a69b2eebf 100644 --- a/avm/res/network/azure-firewall/tests/e2e/max/main.test.bicep +++ b/avm/res/network/azure-firewall/tests/e2e/max/main.test.bicep @@ -61,139 +61,144 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId - applicationRuleCollections: [ - { - name: 'allow-app-rules' - properties: { - action: { - type: 'allow' - } - priority: 100 - rules: [ - { - fqdnTags: [ - 'AppServiceEnvironment' - 'WindowsUpdate' - ] - name: 'allow-ase-tags' - protocols: [ - { - port: '80' - protocolType: 'HTTP' - } - { - port: '443' - protocolType: 'HTTPS' - } - ] - sourceAddresses: [ - '*' - ] +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId + applicationRuleCollections: [ + { + name: 'allow-app-rules' + properties: { + action: { + type: 'allow' } + priority: 100 + rules: [ + { + fqdnTags: [ + 'AppServiceEnvironment' + 'WindowsUpdate' + ] + name: 'allow-ase-tags' + protocols: [ + { + port: '80' + protocolType: 'HTTP' + } + { + port: '443' + protocolType: 'HTTPS' + } + ] + sourceAddresses: [ + '*' + ] + } + { + name: 'allow-ase-management' + protocols: [ + { + port: '80' + protocolType: 'HTTP' + } + { + port: '443' + protocolType: 'HTTPS' + } + ] + sourceAddresses: [ + '*' + ] + targetFqdns: [ + 'bing.com' + ] + } + ] + } + } + ] + publicIPResourceID: nestedDependencies.outputs.publicIPResourceId + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ { - name: 'allow-ase-management' - protocols: [ - { - port: '80' - protocolType: 'HTTP' - } - { - port: '443' - protocolType: 'HTTPS' - } - ] - sourceAddresses: [ - '*' - ] - targetFqdns: [ - 'bing.com' - ] + category: 'AllMetrics' } ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - publicIPResourceID: nestedDependencies.outputs.publicIPResourceId - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - networkRuleCollections: [ - { - name: 'allow-network-rules' - properties: { - action: { - type: 'allow' - } - priority: 100 - rules: [ - { - destinationAddresses: [ - '*' - ] - destinationPorts: [ - '12000' - '123' - ] - name: 'allow-ntp' - protocols: [ - 'Any' - ] - sourceAddresses: [ - '*' - ] + networkRuleCollections: [ + { + name: 'allow-network-rules' + properties: { + action: { + type: 'allow' } - ] + priority: 100 + rules: [ + { + destinationAddresses: [ + '*' + ] + destinationPorts: [ + '12000' + '123' + ] + name: 'allow-ntp' + protocols: [ + 'Any' + ] + sourceAddresses: [ + '*' + ] + } + ] + } } + ] + 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' + } + ] + zones: [ + '1' + '2' + '3' + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - 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' - } - ] - zones: [ - '1' - '2' - '3' - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/network/azure-firewall/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/azure-firewall/tests/e2e/waf-aligned/main.test.bicep index 61cca78551..ca84384701 100644 --- a/avm/res/network/azure-firewall/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/azure-firewall/tests/e2e/waf-aligned/main.test.bicep @@ -61,118 +61,120 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId - applicationRuleCollections: [ - { - name: 'allow-app-rules' - properties: { - action: { - type: 'allow' - } - priority: 100 - rules: [ - { - fqdnTags: [ - 'AppServiceEnvironment' - 'WindowsUpdate' - ] - name: 'allow-ase-tags' - protocols: [ - { - port: '80' - protocolType: 'HTTP' - } - { - port: '443' - protocolType: 'HTTPS' - } - ] - sourceAddresses: [ - '*' - ] +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId + applicationRuleCollections: [ + { + name: 'allow-app-rules' + properties: { + action: { + type: 'allow' } + priority: 100 + rules: [ + { + fqdnTags: [ + 'AppServiceEnvironment' + 'WindowsUpdate' + ] + name: 'allow-ase-tags' + protocols: [ + { + port: '80' + protocolType: 'HTTP' + } + { + port: '443' + protocolType: 'HTTPS' + } + ] + sourceAddresses: [ + '*' + ] + } + { + name: 'allow-ase-management' + protocols: [ + { + port: '80' + protocolType: 'HTTP' + } + { + port: '443' + protocolType: 'HTTPS' + } + ] + sourceAddresses: [ + '*' + ] + targetFqdns: [ + 'bing.com' + ] + } + ] + } + } + ] + publicIPResourceID: nestedDependencies.outputs.publicIPResourceId + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ { - name: 'allow-ase-management' - protocols: [ - { - port: '80' - protocolType: 'HTTP' - } - { - port: '443' - protocolType: 'HTTPS' - } - ] - sourceAddresses: [ - '*' - ] - targetFqdns: [ - 'bing.com' - ] + category: 'AllMetrics' } ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } - } - ] - publicIPResourceID: nestedDependencies.outputs.publicIPResourceId - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - networkRuleCollections: [ - { - name: 'allow-network-rules' - properties: { - action: { - type: 'allow' - } - priority: 100 - rules: [ - { - destinationAddresses: [ - '*' - ] - destinationPorts: [ - '12000' - '123' - ] - name: 'allow-ntp' - protocols: [ - 'Any' - ] - sourceAddresses: [ - '*' - ] + ] + networkRuleCollections: [ + { + name: 'allow-network-rules' + properties: { + action: { + type: 'allow' } - ] + priority: 100 + rules: [ + { + destinationAddresses: [ + '*' + ] + destinationPorts: [ + '12000' + '123' + ] + name: 'allow-ntp' + protocols: [ + 'Any' + ] + sourceAddresses: [ + '*' + ] + } + ] + } } + ] + zones: [ + '1' + '2' + '3' + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - zones: [ - '1' - '2' - '3' - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/network/bastion-host/main.bicep b/avm/res/network/bastion-host/main.bicep index c7e49dc622..0ff22f10f2 100644 --- a/avm/res/network/bastion-host/main.bicep +++ b/avm/res/network/bastion-host/main.bicep @@ -66,16 +66,21 @@ param enableTelemetry bool = true var ipConfigurations = [ { name: 'IpConfAzureBastionSubnet' - properties: union({ + properties: union( + { subnet: { 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 + id: !empty(bastionSubnetPublicIpResourceId) + ? bastionSubnetPublicIpResourceId + : publicIPAddress.outputs.resourceId } - }) + } + ) } ] @@ -85,58 +90,76 @@ 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-bastionhost.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-bastionhost.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} -module publicIPAddress 'br/public:avm/res/network/public-ip-address:0.2.1' = if (empty(bastionSubnetPublicIpResourceId)) { - name: '${uniqueString(deployment().name, location)}-Bastion-PIP' - params: { - name: publicIPAddressObject.name - enableTelemetry: enableTelemetry - location: location - lock: lock - diagnosticSettings: publicIPAddressObject.?diagnosticSettings - publicIPAddressVersion: contains(publicIPAddressObject, 'publicIPAddressVersion') ? publicIPAddressObject.publicIPAddressVersion : 'IPv4' - publicIPAllocationMethod: contains(publicIPAddressObject, 'publicIPAllocationMethod') ? publicIPAddressObject.publicIPAllocationMethod : 'Static' - publicIpPrefixResourceId: contains(publicIPAddressObject, 'publicIPPrefixResourceId') ? publicIPAddressObject.publicIPPrefixResourceId : '' - roleAssignments: contains(publicIPAddressObject, 'roleAssignments') ? publicIPAddressObject.roleAssignments : [] - skuName: contains(publicIPAddressObject, 'skuName') ? publicIPAddressObject.skuName : 'Standard' - skuTier: contains(publicIPAddressObject, 'skuTier') ? publicIPAddressObject.skuTier : 'Regional' - tags: publicIPAddressObject.?tags ?? tags - zones: contains(publicIPAddressObject, 'zones') ? publicIPAddressObject.zones : [] +module publicIPAddress 'br/public:avm/res/network/public-ip-address:0.2.1' = + if (empty(bastionSubnetPublicIpResourceId)) { + name: '${uniqueString(deployment().name, location)}-Bastion-PIP' + params: { + name: publicIPAddressObject.name + enableTelemetry: enableTelemetry + location: location + lock: lock + diagnosticSettings: publicIPAddressObject.?diagnosticSettings + publicIPAddressVersion: contains(publicIPAddressObject, 'publicIPAddressVersion') + ? publicIPAddressObject.publicIPAddressVersion + : 'IPv4' + publicIPAllocationMethod: contains(publicIPAddressObject, 'publicIPAllocationMethod') + ? publicIPAddressObject.publicIPAllocationMethod + : 'Static' + publicIpPrefixResourceId: contains(publicIPAddressObject, 'publicIPPrefixResourceId') + ? publicIPAddressObject.publicIPPrefixResourceId + : '' + roleAssignments: contains(publicIPAddressObject, 'roleAssignments') ? publicIPAddressObject.roleAssignments : [] + skuName: contains(publicIPAddressObject, 'skuName') ? publicIPAddressObject.skuName : 'Standard' + skuTier: contains(publicIPAddressObject, 'skuTier') ? publicIPAddressObject.skuTier : 'Regional' + tags: publicIPAddressObject.?tags ?? tags + zones: contains(publicIPAddressObject, 'zones') ? publicIPAddressObject.zones : [] + } } -} -var bastionpropertiesVar = union({ +var bastionpropertiesVar = union( + { scaleUnits: skuName == 'Basic' ? 2 : scaleUnits ipConfigurations: ipConfigurations enableKerberos: enableKerberos - }, (skuName == 'Standard' ? { - enableTunneling: skuName == 'Standard' - disableCopyPaste: disableCopyPaste - enableFileCopy: enableFileCopy - enableIpConnect: enableIpConnect - enableShareableLink: enableShareableLink - } : {}) + }, + (skuName == 'Standard' + ? { + enableTunneling: skuName == 'Standard' + disableCopyPaste: disableCopyPaste + enableFileCopy: enableFileCopy + enableIpConnect: enableIpConnect + enableShareableLink: enableShareableLink + } + : {}) ) resource azureBastion 'Microsoft.Network/bastionHosts@2022-11-01' = { @@ -149,46 +172,59 @@ resource azureBastion 'Microsoft.Network/bastionHosts@2022-11-01' = { properties: bastionpropertiesVar } -resource azureBastion_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.' +resource azureBastion_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: azureBastion } - scope: azureBastion -} -resource azureBastion_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource azureBastion_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: azureBastion } - scope: azureBastion -}] - -resource azureBastion_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(azureBastion.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +] + +resource azureBastion_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(azureBastion.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: azureBastion } - scope: azureBastion -}] +] @description('The resource group the Azure Bastion was deployed into.') output resourceGroupName string = resourceGroup().name diff --git a/avm/res/network/bastion-host/main.json b/avm/res/network/bastion-host/main.json index d16ef2479c..d0d7428e5d 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.25.53.49325", - "templateHash": "403145241490619459" + "version": "0.26.54.24096", + "templateHash": "6331481515117626704" }, "name": "Bastion Hosts", "description": "This module deploys a Bastion Host.", 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 7aaeca854b..7ae927a6ad 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 @@ -60,54 +60,56 @@ 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 - virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId - publicIPAddressObject: { - name: '${namePrefix}${serviceShort}001-pip' - allocationMethod: 'Static' - publicIPPrefixResourceId: '' - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - ] - skuName: 'Standard' - skuTier: 'Regional' - zones: [ - '1' - '2' - '3' - ] - 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 + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId + publicIPAddressObject: { + name: '${namePrefix}${serviceShort}001-pip' + allocationMethod: 'Static' + publicIPPrefixResourceId: '' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + skuName: 'Standard' + skuTier: 'Regional' + zones: [ + '1' + '2' + '3' + ] + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] 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 27e87ef3c2..f103fca5f0 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 @@ -45,15 +45,17 @@ 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 - virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId +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 + } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] 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 fb76689996..9ade33f499 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 @@ -61,58 +61,63 @@ 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 - virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId - bastionSubnetPublicIpResourceId: nestedDependencies.outputs.publicIPResourceId - diagnosticSettings: [ - { - name: 'customSetting' - 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 + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId + bastionSubnetPublicIpResourceId: nestedDependencies.outputs.publicIPResourceId + diagnosticSettings: [ + { + name: 'customSetting' + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + disableCopyPaste: true + enableFileCopy: false + enableIpConnect: false + enableShareableLink: false + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - disableCopyPaste: true - enableFileCopy: false - enableIpConnect: false - enableShareableLink: false - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + 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' + } + ] + scaleUnits: 4 + skuName: 'Standard' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - { - 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' - } - ] - scaleUnits: 4 - skuName: 'Standard' - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] 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 ac7d900ba9..6fb0ed60a0 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 @@ -60,37 +60,39 @@ 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 - virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId - bastionSubnetPublicIpResourceId: nestedDependencies.outputs.publicIPResourceId - diagnosticSettings: [ - { - name: 'customSetting' - 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 + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId + bastionSubnetPublicIpResourceId: nestedDependencies.outputs.publicIPResourceId + diagnosticSettings: [ + { + name: 'customSetting' + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + disableCopyPaste: true + enableFileCopy: false + enableIpConnect: false + enableShareableLink: false + scaleUnits: 4 + skuName: 'Standard' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - disableCopyPaste: true - enableFileCopy: false - enableIpConnect: false - enableShareableLink: false - scaleUnits: 4 - skuName: 'Standard' - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/network/connection/main.bicep b/avm/res/network/connection/main.bicep index 576ef2253f..5f059b6774 100644 --- a/avm/res/network/connection/main.bicep +++ b/avm/res/network/connection/main.bicep @@ -96,23 +96,24 @@ param authorizationKey string = '' @description('Optional. The local network gateway. Used for connection type [IPsec].') param localNetworkGateway2 object = {} -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-connection.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-connection.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource connection 'Microsoft.Network/connections@2023-04-01' = { name: name @@ -132,32 +133,37 @@ resource connection 'Microsoft.Network/connections@2023-04-01' = { authorizationKey: connectionType == 'ExpressRoute' && !empty(authorizationKey) ? authorizationKey : null sharedKey: connectionType != 'ExpressRoute' ? vpnSharedKey : null usePolicyBasedTrafficSelectors: usePolicyBasedTrafficSelectors - ipsecPolicies: !empty(customIPSecPolicy.ipsecEncryption) ? [ - { - saLifeTimeSeconds: customIPSecPolicy.saLifeTimeSeconds - saDataSizeKilobytes: customIPSecPolicy.saDataSizeKilobytes - ipsecEncryption: customIPSecPolicy.ipsecEncryption - ipsecIntegrity: customIPSecPolicy.ipsecIntegrity - ikeEncryption: customIPSecPolicy.ikeEncryption - ikeIntegrity: customIPSecPolicy.ikeIntegrity - dhGroup: customIPSecPolicy.dhGroup - pfsGroup: customIPSecPolicy.pfsGroup - } - ] : customIPSecPolicy.ipsecEncryption + ipsecPolicies: !empty(customIPSecPolicy.ipsecEncryption) + ? [ + { + saLifeTimeSeconds: customIPSecPolicy.saLifeTimeSeconds + saDataSizeKilobytes: customIPSecPolicy.saDataSizeKilobytes + ipsecEncryption: customIPSecPolicy.ipsecEncryption + ipsecIntegrity: customIPSecPolicy.ipsecIntegrity + ikeEncryption: customIPSecPolicy.ikeEncryption + ikeIntegrity: customIPSecPolicy.ikeIntegrity + dhGroup: customIPSecPolicy.dhGroup + pfsGroup: customIPSecPolicy.pfsGroup + } + ] + : customIPSecPolicy.ipsecEncryption routingWeight: routingWeight enableBgp: enableBgp useLocalAzureIpAddress: connectionType == 'IPsec' ? useLocalAzureIpAddress : null } } -resource connection_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.' +resource connection_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: connection } - scope: connection -} @description('The resource group the remote connection was deployed into.') output resourceGroupName string = resourceGroup().name diff --git a/avm/res/network/connection/main.json b/avm/res/network/connection/main.json index 5747c1044f..46cc731506 100644 --- a/avm/res/network/connection/main.json +++ b/avm/res/network/connection/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16775998299537501869" + "version": "0.26.54.24096", + "templateHash": "17255378550715069548" }, "name": "Virtual Network Gateway Connections", "description": "This module deploys a Virtual Network Gateway Connection.", diff --git a/avm/res/network/connection/tests/e2e/defaults/main.test.bicep b/avm/res/network/connection/tests/e2e/defaults/main.test.bicep index 22eb55b153..173f43b4af 100644 --- a/avm/res/network/connection/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/connection/tests/e2e/defaults/main.test.bicep @@ -54,22 +54,24 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - virtualNetworkGateway1: { - id: nestedDependencies.outputs.primaryVNETGatewayResourceID - } - virtualNetworkGateway2: { - id: nestedDependencies.outputs.secondaryVNETGatewayResourceID +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + virtualNetworkGateway1: { + id: nestedDependencies.outputs.primaryVNETGatewayResourceID + } + virtualNetworkGateway2: { + id: nestedDependencies.outputs.secondaryVNETGatewayResourceID + } + connectionType: 'Vnet2Vnet' + vpnSharedKey: password } - connectionType: 'Vnet2Vnet' - vpnSharedKey: password + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/network/connection/tests/e2e/max/main.test.bicep b/avm/res/network/connection/tests/e2e/max/main.test.bicep index 4a085c807f..e1b1154c01 100644 --- a/avm/res/network/connection/tests/e2e/max/main.test.bicep +++ b/avm/res/network/connection/tests/e2e/max/main.test.bicep @@ -54,34 +54,36 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - virtualNetworkGateway1: { - id: nestedDependencies.outputs.primaryVNETGatewayResourceID - } - enableBgp: false - usePolicyBasedTrafficSelectors: false - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - virtualNetworkGateway2: { - id: nestedDependencies.outputs.secondaryVNETGatewayResourceID - } - connectionType: 'Vnet2Vnet' - dpdTimeoutSeconds: 45 - vpnSharedKey: password - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + virtualNetworkGateway1: { + id: nestedDependencies.outputs.primaryVNETGatewayResourceID + } + enableBgp: false + usePolicyBasedTrafficSelectors: false + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + virtualNetworkGateway2: { + id: nestedDependencies.outputs.secondaryVNETGatewayResourceID + } + connectionType: 'Vnet2Vnet' + dpdTimeoutSeconds: 45 + vpnSharedKey: password + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/network/connection/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/connection/tests/e2e/waf-aligned/main.test.bicep index e24ad2beb9..4d13294954 100644 --- a/avm/res/network/connection/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/connection/tests/e2e/waf-aligned/main.test.bicep @@ -54,31 +54,33 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - virtualNetworkGateway1: { - id: nestedDependencies.outputs.primaryVNETGatewayResourceID - } - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - virtualNetworkGateway2: { - id: nestedDependencies.outputs.secondaryVNETGatewayResourceID - } - connectionType: 'Vnet2Vnet' - vpnSharedKey: password - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + virtualNetworkGateway1: { + id: nestedDependencies.outputs.primaryVNETGatewayResourceID + } + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + virtualNetworkGateway2: { + id: nestedDependencies.outputs.secondaryVNETGatewayResourceID + } + connectionType: 'Vnet2Vnet' + vpnSharedKey: password + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/network/ddos-protection-plan/main.bicep b/avm/res/network/ddos-protection-plan/main.bicep index 3133dab953..7701fad812 100644 --- a/avm/res/network/ddos-protection-plan/main.bicep +++ b/avm/res/network/ddos-protection-plan/main.bicep @@ -25,27 +25,34 @@ 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-ddosprotectionplan.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-ddosprotectionplan.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource ddosProtectionPlan 'Microsoft.Network/ddosProtectionPlans@2023-04-01' = { name: name @@ -54,28 +61,37 @@ resource ddosProtectionPlan 'Microsoft.Network/ddosProtectionPlans@2023-04-01' = properties: {} } -resource ddosProtectionPlan_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.' +resource ddosProtectionPlan_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: ddosProtectionPlan } - scope: ddosProtectionPlan -} -resource ddosProtectionPlan_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(ddosProtectionPlan.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource ddosProtectionPlan_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(ddosProtectionPlan.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: ddosProtectionPlan } - scope: ddosProtectionPlan -}] +] @description('The resource group the DDOS protection plan was deployed into.') output resourceGroupName string = resourceGroup().name diff --git a/avm/res/network/ddos-protection-plan/main.json b/avm/res/network/ddos-protection-plan/main.json index a65b5d480d..79a9acca63 100644 --- a/avm/res/network/ddos-protection-plan/main.json +++ b/avm/res/network/ddos-protection-plan/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "1916218161096059486" + "version": "0.26.54.24096", + "templateHash": "1494680317385040277" }, "name": "DDoS Protection Plans", "description": "This module deploys a DDoS Protection Plan.", diff --git a/avm/res/network/ddos-protection-plan/tests/e2e/max/dependencies.bicep b/avm/res/network/ddos-protection-plan/tests/e2e/max/dependencies.bicep index a7f42aee7b..7be39e253a 100644 --- a/avm/res/network/ddos-protection-plan/tests/e2e/max/dependencies.bicep +++ b/avm/res/network/ddos-protection-plan/tests/e2e/max/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/network/ddos-protection-plan/tests/e2e/max/main.test.bicep b/avm/res/network/ddos-protection-plan/tests/e2e/max/main.test.bicep index cb5de1c255..5b2e34186a 100644 --- a/avm/res/network/ddos-protection-plan/tests/e2e/max/main.test.bicep +++ b/avm/res/network/ddos-protection-plan/tests/e2e/max/main.test.bicep @@ -66,7 +66,10 @@ module testDeployment '../../../main.bicep' = { principalType: 'ServicePrincipal' } { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) principalId: nestedDependencies.outputs.managedIdentityPrincipalId principalType: 'ServicePrincipal' } diff --git a/avm/res/network/dns-forwarding-ruleset/forwarding-rule/main.json b/avm/res/network/dns-forwarding-ruleset/forwarding-rule/main.json index 3050c7c9b5..a78e018085 100644 --- a/avm/res/network/dns-forwarding-ruleset/forwarding-rule/main.json +++ b/avm/res/network/dns-forwarding-ruleset/forwarding-rule/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16468651666444588102" + "version": "0.26.54.24096", + "templateHash": "11159744121670173662" }, "name": "Dns Forwarding Rulesets Forwarding Rules", "description": "This template deploys Forwarding Rule in a Dns Forwarding Ruleset.", diff --git a/avm/res/network/dns-forwarding-ruleset/main.bicep b/avm/res/network/dns-forwarding-ruleset/main.bicep index b5b04038aa..2595bcf979 100644 --- a/avm/res/network/dns-forwarding-ruleset/main.bicep +++ b/avm/res/network/dns-forwarding-ruleset/main.bicep @@ -32,86 +32,117 @@ param enableTelemetry bool = true var 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') - 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'DNS Resolver Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d' + ) + 'DNS Zone Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'befefa01-2a29-4197-83a8-272ff33ce314' + ) + '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') + '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 (Preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-dnsforwardingruleset.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-dnsforwardingruleset.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource dnsForwardingRuleset 'Microsoft.Network/dnsForwardingRulesets@2022-07-01' = { name: name location: location tags: tags properties: { - dnsResolverOutboundEndpoints: [for dnsForwardingRulesetOutboundEndpointResourceId in dnsForwardingRulesetOutboundEndpointResourceIds: { - id: dnsForwardingRulesetOutboundEndpointResourceId - }] + dnsResolverOutboundEndpoints: [ + for dnsForwardingRulesetOutboundEndpointResourceId in dnsForwardingRulesetOutboundEndpointResourceIds: { + id: dnsForwardingRulesetOutboundEndpointResourceId + } + ] } } -module dnsForwardingRuleset_forwardingRule 'forwarding-rule/main.bicep' = [for (forwardingRule, index) in (forwardingRules ?? []): { - name: '${uniqueString(deployment().name, location)}-forwardingRule-${index}' - params: { - dnsForwardingRulesetName: dnsForwardingRuleset.name - name: forwardingRule.?name - forwardingRuleState: forwardingRule.?forwardingRuleState ?? 'Enabled' - domainName: forwardingRule.?domainName - targetDnsServers: forwardingRule.?targetDnsServers - metadata: forwardingRule.?metadata +module dnsForwardingRuleset_forwardingRule 'forwarding-rule/main.bicep' = [ + for (forwardingRule, index) in (forwardingRules ?? []): { + name: '${uniqueString(deployment().name, location)}-forwardingRule-${index}' + params: { + dnsForwardingRulesetName: dnsForwardingRuleset.name + name: forwardingRule.?name + forwardingRuleState: forwardingRule.?forwardingRuleState ?? 'Enabled' + domainName: forwardingRule.?domainName + targetDnsServers: forwardingRule.?targetDnsServers + metadata: forwardingRule.?metadata + } } -}] - -module dnsForwardingRuleset_virtualNetworkLinks 'virtual-network-link/main.bicep' = [for (vnetId, index) in (vNetLinks ?? []): { - name: '${uniqueString(deployment().name, location)}-virtualNetworkLink-${index}' - params: { - dnsForwardingRulesetName: dnsForwardingRuleset.name - virtualNetworkResourceId: !empty(vNetLinks) ? vnetId : null +] + +module dnsForwardingRuleset_virtualNetworkLinks 'virtual-network-link/main.bicep' = [ + for (vnetId, index) in (vNetLinks ?? []): { + name: '${uniqueString(deployment().name, location)}-virtualNetworkLink-${index}' + params: { + dnsForwardingRulesetName: dnsForwardingRuleset.name + virtualNetworkResourceId: !empty(vNetLinks) ? vnetId : null + } } -}] - -resource dnsForwardingRuleset_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.' +] + +resource dnsForwardingRuleset_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: dnsForwardingRuleset } - scope: dnsForwardingRuleset -} -resource dnsForwardingRuleset_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(dnsForwardingRuleset.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource dnsForwardingRuleset_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(dnsForwardingRuleset.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: dnsForwardingRuleset } - scope: dnsForwardingRuleset -}] +] @description('The resource group the DNS Forwarding Ruleset was deployed into.') output resourceGroupName string = resourceGroup().name diff --git a/avm/res/network/dns-forwarding-ruleset/main.json b/avm/res/network/dns-forwarding-ruleset/main.json index c591d647ed..75b2de3482 100644 --- a/avm/res/network/dns-forwarding-ruleset/main.json +++ b/avm/res/network/dns-forwarding-ruleset/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4310630541865622256" + "version": "0.26.54.24096", + "templateHash": "12711184694701779710" }, "name": "Dns Forwarding Rulesets", "description": "This template deploys an dns forwarding ruleset.", @@ -359,8 +359,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16468651666444588102" + "version": "0.26.54.24096", + "templateHash": "11159744121670173662" }, "name": "Dns Forwarding Rulesets Forwarding Rules", "description": "This template deploys Forwarding Rule in a Dns Forwarding Ruleset.", @@ -484,8 +484,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2776981605709910245" + "version": "0.26.54.24096", + "templateHash": "15095816376592886095" }, "name": "Dns Forwarding Rulesets Virtual Network Links", "description": "This template deploys Virtual Network Link in a Dns Forwarding Ruleset.", diff --git a/avm/res/network/dns-forwarding-ruleset/tests/e2e/defaults/dependencies.bicep b/avm/res/network/dns-forwarding-ruleset/tests/e2e/defaults/dependencies.bicep index 41fbb37c7e..946812afa8 100644 --- a/avm/res/network/dns-forwarding-ruleset/tests/e2e/defaults/dependencies.bicep +++ b/avm/res/network/dns-forwarding-ruleset/tests/e2e/defaults/dependencies.bicep @@ -18,7 +18,9 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { addressPrefix ] } - subnets: map(range(0, 2), i => { + subnets: map( + range(0, 2), + i => { name: 'subnet-${i}' properties: { addressPrefix: cidrSubnet(addressPrefix, 25, i) @@ -31,7 +33,8 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { } ] } - }) + } + ) } } diff --git a/avm/res/network/dns-forwarding-ruleset/tests/e2e/defaults/main.test.bicep b/avm/res/network/dns-forwarding-ruleset/tests/e2e/defaults/main.test.bicep index 8e5de6d3ad..5c983ca0b6 100644 --- a/avm/res/network/dns-forwarding-ruleset/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/dns-forwarding-ruleset/tests/e2e/defaults/main.test.bicep @@ -46,17 +46,19 @@ 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' - dnsForwardingRulesetOutboundEndpointResourceIds: [ - nestedDependencies.outputs.dnsResolverOutboundEndpointsResourceId +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + dnsForwardingRulesetOutboundEndpointResourceIds: [ + nestedDependencies.outputs.dnsResolverOutboundEndpointsResourceId + ] + location: resourceLocation + } + dependsOn: [ + nestedDependencies ] - location: resourceLocation } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/network/dns-forwarding-ruleset/tests/e2e/max/dependencies.bicep b/avm/res/network/dns-forwarding-ruleset/tests/e2e/max/dependencies.bicep index d1fb3445ee..d98ebb0285 100644 --- a/avm/res/network/dns-forwarding-ruleset/tests/e2e/max/dependencies.bicep +++ b/avm/res/network/dns-forwarding-ruleset/tests/e2e/max/dependencies.bicep @@ -21,7 +21,9 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { addressPrefix ] } - subnets: map(range(0, 2), i => { + subnets: map( + range(0, 2), + i => { name: 'subnet-${i}' properties: { addressPrefix: cidrSubnet(addressPrefix, 25, i) @@ -34,7 +36,8 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { } ] } - }) + } + ) } } @@ -45,7 +48,6 @@ resource dnsResolver 'Microsoft.Network/dnsResolvers@2022-07-01' = { virtualNetwork: { id: virtualNetwork.id } - } } diff --git a/avm/res/network/dns-forwarding-ruleset/tests/e2e/max/main.test.bicep b/avm/res/network/dns-forwarding-ruleset/tests/e2e/max/main.test.bicep index 8bb2dacb7f..69be2f690c 100644 --- a/avm/res/network/dns-forwarding-ruleset/tests/e2e/max/main.test.bicep +++ b/avm/res/network/dns-forwarding-ruleset/tests/e2e/max/main.test.bicep @@ -47,59 +47,64 @@ 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 - dnsForwardingRulesetOutboundEndpointResourceIds: [ - nestedDependencies.outputs.dnsResolverOutboundEndpointsId - ] - vNetLinks: [ - nestedDependencies.outputs.virtualNetworkResourceId - ] - forwardingRules: [ - { - name: 'rule1' - forwardingRuleState: 'Enabled' - domainName: 'contoso.' - targetDnsServers: [ - { - ipAddress: '192.168.0.1' - port: '53' - } - ] +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 + dnsForwardingRulesetOutboundEndpointResourceIds: [ + nestedDependencies.outputs.dnsResolverOutboundEndpointsId + ] + vNetLinks: [ + nestedDependencies.outputs.virtualNetworkResourceId + ] + forwardingRules: [ + { + name: 'rule1' + forwardingRuleState: 'Enabled' + domainName: 'contoso.' + targetDnsServers: [ + { + ipAddress: '192.168.0.1' + port: '53' + } + ] + } + ] + 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' + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - { - 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' - } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/network/dns-forwarding-ruleset/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/network/dns-forwarding-ruleset/tests/e2e/waf-aligned/dependencies.bicep index d1fb3445ee..d98ebb0285 100644 --- a/avm/res/network/dns-forwarding-ruleset/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/network/dns-forwarding-ruleset/tests/e2e/waf-aligned/dependencies.bicep @@ -21,7 +21,9 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { addressPrefix ] } - subnets: map(range(0, 2), i => { + subnets: map( + range(0, 2), + i => { name: 'subnet-${i}' properties: { addressPrefix: cidrSubnet(addressPrefix, 25, i) @@ -34,7 +36,8 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { } ] } - }) + } + ) } } @@ -45,7 +48,6 @@ resource dnsResolver 'Microsoft.Network/dnsResolvers@2022-07-01' = { virtualNetwork: { id: virtualNetwork.id } - } } diff --git a/avm/res/network/dns-forwarding-ruleset/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/dns-forwarding-ruleset/tests/e2e/waf-aligned/main.test.bicep index 82c1add6d7..3540444952 100644 --- a/avm/res/network/dns-forwarding-ruleset/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/dns-forwarding-ruleset/tests/e2e/waf-aligned/main.test.bicep @@ -47,26 +47,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 - dnsForwardingRulesetOutboundEndpointResourceIds: [ - nestedDependencies.outputs.dnsResolverOutboundEndpointsId - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +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 + dnsForwardingRulesetOutboundEndpointResourceIds: [ + nestedDependencies.outputs.dnsResolverOutboundEndpointsId + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/network/dns-forwarding-ruleset/virtual-network-link/main.json b/avm/res/network/dns-forwarding-ruleset/virtual-network-link/main.json index 1416d30645..caaefb759a 100644 --- a/avm/res/network/dns-forwarding-ruleset/virtual-network-link/main.json +++ b/avm/res/network/dns-forwarding-ruleset/virtual-network-link/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2776981605709910245" + "version": "0.26.54.24096", + "templateHash": "15095816376592886095" }, "name": "Dns Forwarding Rulesets Virtual Network Links", "description": "This template deploys Virtual Network Link in a Dns Forwarding Ruleset.", diff --git a/avm/res/network/dns-resolver/inbound-endpoint/main.json b/avm/res/network/dns-resolver/inbound-endpoint/main.json index 23a17b28c4..8830c57a9c 100644 --- a/avm/res/network/dns-resolver/inbound-endpoint/main.json +++ b/avm/res/network/dns-resolver/inbound-endpoint/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "8672047882378700944" + "version": "0.26.54.24096", + "templateHash": "13768999645959207906" }, "name": "DNS Resolver Inbound Endpoint", "description": "This module deploys a DNS Resolver Inbound Endpoint.", diff --git a/avm/res/network/dns-resolver/main.bicep b/avm/res/network/dns-resolver/main.bicep index ebb617fd7d..067169222c 100644 --- a/avm/res/network/dns-resolver/main.bicep +++ b/avm/res/network/dns-resolver/main.bicep @@ -32,34 +32,56 @@ param enableTelemetry bool = true var 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') + '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') + '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 (Preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-dnsresolver.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-dnsresolver.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource dnsResolver 'Microsoft.Network/dnsResolvers@2022-07-01' = { name: name @@ -72,52 +94,65 @@ resource dnsResolver 'Microsoft.Network/dnsResolvers@2022-07-01' = { } } -resource dnsResolver_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.' +resource dnsResolver_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: dnsResolver } - scope: dnsResolver -} -resource dnsResolver_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(dnsResolver.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource dnsResolver_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(dnsResolver.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: dnsResolver } - scope: dnsResolver -}] - -module dnsResolver_inboundEndpoints 'inbound-endpoint/main.bicep' = [for (inboundEndpoint, index) in (inboundEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-dnsResolver-inbound-${index}' - params: { - name: inboundEndpoint.name - tags: inboundEndpoint.?tags ?? tags - location: inboundEndpoint.?location ?? location - dnsResolverName: dnsResolver.name - subnetResourceId: inboundEndpoint.subnetResourceId - privateIpAddress: inboundEndpoint.?privateIpAddress - privateIpAllocationMethod: inboundEndpoint.?privateIpAllocationMethod +] + +module dnsResolver_inboundEndpoints 'inbound-endpoint/main.bicep' = [ + for (inboundEndpoint, index) in (inboundEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-dnsResolver-inbound-${index}' + params: { + name: inboundEndpoint.name + tags: inboundEndpoint.?tags ?? tags + location: inboundEndpoint.?location ?? location + dnsResolverName: dnsResolver.name + subnetResourceId: inboundEndpoint.subnetResourceId + privateIpAddress: inboundEndpoint.?privateIpAddress + privateIpAllocationMethod: inboundEndpoint.?privateIpAllocationMethod + } } -}] - -module dnsResolver_outboundEndpoints 'outbound-endpoint/main.bicep' = [for (outboundEndpoint, index) in (outboundEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-dnsResolver-outbound-${index}' - params: { - name: outboundEndpoint.name - tags: outboundEndpoint.?tags ?? tags - location: outboundEndpoint.?location ?? location - dnsResolverName: dnsResolver.name - subnetResourceId: outboundEndpoint.subnetResourceId +] + +module dnsResolver_outboundEndpoints 'outbound-endpoint/main.bicep' = [ + for (outboundEndpoint, index) in (outboundEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-dnsResolver-outbound-${index}' + params: { + name: outboundEndpoint.name + tags: outboundEndpoint.?tags ?? tags + location: outboundEndpoint.?location ?? location + dnsResolverName: dnsResolver.name + subnetResourceId: outboundEndpoint.subnetResourceId + } } -}] +] @description('The resource group the DNS Private Resolver was deployed into.') output resourceGroupName string = resourceGroup().name diff --git a/avm/res/network/dns-resolver/main.json b/avm/res/network/dns-resolver/main.json index be81467fb9..a1d1246acc 100644 --- a/avm/res/network/dns-resolver/main.json +++ b/avm/res/network/dns-resolver/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11674721033032796270" + "version": "0.26.54.24096", + "templateHash": "16134836553135167384" }, "name": "DNS Resolver", "description": "This module deploys a DNS Resolver.", @@ -379,8 +379,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "8672047882378700944" + "version": "0.26.54.24096", + "templateHash": "13768999645959207906" }, "name": "DNS Resolver Inbound Endpoint", "description": "This module deploys a DNS Resolver Inbound Endpoint.", @@ -530,8 +530,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "7237665514415394760" + "version": "0.26.54.24096", + "templateHash": "6638776759595697100" }, "name": "DNS Resolver Outbound Endpoint", "description": "This module deploys a DNS Resolver Outbound Endpoint.", diff --git a/avm/res/network/dns-resolver/outbound-endpoint/main.json b/avm/res/network/dns-resolver/outbound-endpoint/main.json index b287446a50..2db11de3ef 100644 --- a/avm/res/network/dns-resolver/outbound-endpoint/main.json +++ b/avm/res/network/dns-resolver/outbound-endpoint/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "7237665514415394760" + "version": "0.26.54.24096", + "templateHash": "6638776759595697100" }, "name": "DNS Resolver Outbound Endpoint", "description": "This module deploys a DNS Resolver Outbound Endpoint.", diff --git a/avm/res/network/dns-resolver/tests/e2e/defaults/dependencies.bicep b/avm/res/network/dns-resolver/tests/e2e/defaults/dependencies.bicep index f25a4e5ff7..555c9c977b 100644 --- a/avm/res/network/dns-resolver/tests/e2e/defaults/dependencies.bicep +++ b/avm/res/network/dns-resolver/tests/e2e/defaults/dependencies.bicep @@ -18,7 +18,9 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { addressPrefix ] } - subnets: map(range(0, 2), i => { + subnets: map( + range(0, 2), + i => { name: 'subnet-${i}' properties: { addressPrefix: cidrSubnet(addressPrefix, 25, i) @@ -31,7 +33,8 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { } ] } - }) + } + ) } } diff --git a/avm/res/network/dns-resolver/tests/e2e/defaults/main.test.bicep b/avm/res/network/dns-resolver/tests/e2e/defaults/main.test.bicep index 5bdcb9bd4a..3ce2bbf07e 100644 --- a/avm/res/network/dns-resolver/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/dns-resolver/tests/e2e/defaults/main.test.bicep @@ -46,12 +46,14 @@ 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' - virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId - location: resourceLocation +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId + location: resourceLocation + } } -}] +] diff --git a/avm/res/network/dns-resolver/tests/e2e/max/dependencies.bicep b/avm/res/network/dns-resolver/tests/e2e/max/dependencies.bicep index f25a4e5ff7..555c9c977b 100644 --- a/avm/res/network/dns-resolver/tests/e2e/max/dependencies.bicep +++ b/avm/res/network/dns-resolver/tests/e2e/max/dependencies.bicep @@ -18,7 +18,9 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { addressPrefix ] } - subnets: map(range(0, 2), i => { + subnets: map( + range(0, 2), + i => { name: 'subnet-${i}' properties: { addressPrefix: cidrSubnet(addressPrefix, 25, i) @@ -31,7 +33,8 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { } ] } - }) + } + ) } } diff --git a/avm/res/network/dns-resolver/tests/e2e/max/main.test.bicep b/avm/res/network/dns-resolver/tests/e2e/max/main.test.bicep index a942d6711c..b88dfaa63b 100644 --- a/avm/res/network/dns-resolver/tests/e2e/max/main.test.bicep +++ b/avm/res/network/dns-resolver/tests/e2e/max/main.test.bicep @@ -46,50 +46,55 @@ 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 - virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - 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' - } - ] - inboundEndpoints: [ - { - name: '${namePrefix}${serviceShort}-az-pdnsin-x-001' - subnetResourceId: nestedDependencies.outputs.subnetResourceId_dnsIn +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 + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - outboundEndpoints: [ - { - name: '${namePrefix}${serviceShort}-az-pdnsout-x-001' - subnetResourceId: nestedDependencies.outputs.subnetResourceId_dnsOut + 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' + } + ] + inboundEndpoints: [ + { + name: '${namePrefix}${serviceShort}-az-pdnsin-x-001' + subnetResourceId: nestedDependencies.outputs.subnetResourceId_dnsIn + } + ] + outboundEndpoints: [ + { + name: '${namePrefix}${serviceShort}-az-pdnsout-x-001' + subnetResourceId: nestedDependencies.outputs.subnetResourceId_dnsOut + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/network/dns-resolver/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/network/dns-resolver/tests/e2e/waf-aligned/dependencies.bicep index f25a4e5ff7..555c9c977b 100644 --- a/avm/res/network/dns-resolver/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/network/dns-resolver/tests/e2e/waf-aligned/dependencies.bicep @@ -18,7 +18,9 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { addressPrefix ] } - subnets: map(range(0, 2), i => { + subnets: map( + range(0, 2), + i => { name: 'subnet-${i}' properties: { addressPrefix: cidrSubnet(addressPrefix, 25, i) @@ -31,7 +33,8 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { } ] } - }) + } + ) } } diff --git a/avm/res/network/dns-resolver/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/dns-resolver/tests/e2e/waf-aligned/main.test.bicep index 7f820efb73..04a4057071 100644 --- a/avm/res/network/dns-resolver/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/dns-resolver/tests/e2e/waf-aligned/main.test.bicep @@ -46,33 +46,35 @@ 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 - lock: { - name: 'myCustomLockName' - kind: 'CanNotDelete' - } - virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId - inboundEndpoints: [ - { - name: '${namePrefix}${serviceShort}-az-pdnsin-x-001' - subnetResourceId: nestedDependencies.outputs.subnetResourceId_dnsIn +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 + lock: { + name: 'myCustomLockName' + kind: 'CanNotDelete' } - ] - outboundEndpoints: [ - { - name: '${namePrefix}${serviceShort}-az-pdnsout-x-001' - subnetResourceId: nestedDependencies.outputs.subnetResourceId_dnsOut + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId + inboundEndpoints: [ + { + name: '${namePrefix}${serviceShort}-az-pdnsin-x-001' + subnetResourceId: nestedDependencies.outputs.subnetResourceId_dnsIn + } + ] + outboundEndpoints: [ + { + name: '${namePrefix}${serviceShort}-az-pdnsout-x-001' + subnetResourceId: nestedDependencies.outputs.subnetResourceId_dnsOut + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/network/dns-zone/a/main.bicep b/avm/res/network/dns-zone/a/main.bicep index d291137766..848580c988 100644 --- a/avm/res/network/dns-zone/a/main.bicep +++ b/avm/res/network/dns-zone/a/main.bicep @@ -25,16 +25,40 @@ param roleAssignments roleAssignmentType var 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') + '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') + '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') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } resource dnsZone 'Microsoft.Network/dnsZones@2018-05-01' existing = { name: dnsZoneName @@ -47,25 +71,33 @@ resource A 'Microsoft.Network/dnsZones/A@2018-05-01' = { ARecords: !empty(aRecords) ? aRecords : null metadata: metadata TTL: ttl - targetResource: !empty(targetResourceId) ? { - id: targetResourceId - } : null + targetResource: !empty(targetResourceId) + ? { + id: targetResourceId + } + : null } } -resource A_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(A.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource A_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(A.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: A } - scope: A -}] +] @description('The name of the deployed A record.') output name string = A.name diff --git a/avm/res/network/dns-zone/a/main.json b/avm/res/network/dns-zone/a/main.json index f95aa9a994..8064fe574b 100644 --- a/avm/res/network/dns-zone/a/main.json +++ b/avm/res/network/dns-zone/a/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "1014861232584705848" + "version": "0.26.54.24096", + "templateHash": "4017689599365774964" }, "name": "Public DNS Zone A record", "description": "This module deploys a Public DNS Zone A record.", diff --git a/avm/res/network/dns-zone/aaaa/main.bicep b/avm/res/network/dns-zone/aaaa/main.bicep index 468cf3399c..291ce5ce3a 100644 --- a/avm/res/network/dns-zone/aaaa/main.bicep +++ b/avm/res/network/dns-zone/aaaa/main.bicep @@ -25,16 +25,40 @@ param roleAssignments roleAssignmentType var 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') + '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') + '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') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } resource dnsZone 'Microsoft.Network/dnsZones@2018-05-01' existing = { @@ -48,25 +72,33 @@ resource AAAA 'Microsoft.Network/dnsZones/AAAA@2018-05-01' = { AAAARecords: !empty(aaaaRecords) ? aaaaRecords : null metadata: metadata TTL: ttl - targetResource: !empty(targetResourceId) ? { - id: targetResourceId - } : null + targetResource: !empty(targetResourceId) + ? { + id: targetResourceId + } + : null } } -resource AAAA_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(AAAA.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource AAAA_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(AAAA.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: AAAA } - scope: AAAA -}] +] @description('The name of the deployed AAAA record.') output name string = AAAA.name diff --git a/avm/res/network/dns-zone/aaaa/main.json b/avm/res/network/dns-zone/aaaa/main.json index d0fbec5f0e..60370a5d7d 100644 --- a/avm/res/network/dns-zone/aaaa/main.json +++ b/avm/res/network/dns-zone/aaaa/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17816545426283561774" + "version": "0.26.54.24096", + "templateHash": "3971171413214558899" }, "name": "Public DNS Zone AAAA record", "description": "This module deploys a Public DNS Zone AAAA record.", diff --git a/avm/res/network/dns-zone/caa/main.bicep b/avm/res/network/dns-zone/caa/main.bicep index 72a657fcfc..4f819bdbdf 100644 --- a/avm/res/network/dns-zone/caa/main.bicep +++ b/avm/res/network/dns-zone/caa/main.bicep @@ -22,16 +22,40 @@ param roleAssignments roleAssignmentType var 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') + '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') + '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') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } resource dnsZone 'Microsoft.Network/dnsZones@2018-05-01' existing = { @@ -48,19 +72,25 @@ resource CAA 'Microsoft.Network/dnsZones/CAA@2018-05-01' = { } } -resource CAA_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(CAA.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource CAA_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(CAA.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: CAA } - scope: CAA -}] +] @description('The name of the deployed CAA record.') output name string = CAA.name diff --git a/avm/res/network/dns-zone/caa/main.json b/avm/res/network/dns-zone/caa/main.json index c3008da102..e4be71280c 100644 --- a/avm/res/network/dns-zone/caa/main.json +++ b/avm/res/network/dns-zone/caa/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2222693701620961150" + "version": "0.26.54.24096", + "templateHash": "8677073922032532586" }, "name": "Public DNS Zone CAA record", "description": "This module deploys a Public DNS Zone CAA record.", diff --git a/avm/res/network/dns-zone/cname/main.bicep b/avm/res/network/dns-zone/cname/main.bicep index 9e9a1aa682..71aecd0bb9 100644 --- a/avm/res/network/dns-zone/cname/main.bicep +++ b/avm/res/network/dns-zone/cname/main.bicep @@ -25,16 +25,40 @@ param roleAssignments roleAssignmentType var 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') + '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') + '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') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } resource dnsZone 'Microsoft.Network/dnsZones@2018-05-01' existing = { @@ -48,25 +72,33 @@ resource CNAME 'Microsoft.Network/dnsZones/CNAME@2018-05-01' = { CNAMERecord: !empty(cnameRecord) ? cnameRecord : null metadata: metadata TTL: ttl - targetResource: !empty(targetResourceId) ? { - id: targetResourceId - } : null + targetResource: !empty(targetResourceId) + ? { + id: targetResourceId + } + : null } } -resource CNAME_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(CNAME.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource CNAME_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(CNAME.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: CNAME } - scope: CNAME -}] +] @description('The name of the deployed CNAME record.') output name string = CNAME.name diff --git a/avm/res/network/dns-zone/cname/main.json b/avm/res/network/dns-zone/cname/main.json index ce4232f426..cc733f096f 100644 --- a/avm/res/network/dns-zone/cname/main.json +++ b/avm/res/network/dns-zone/cname/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11680687850109857660" + "version": "0.26.54.24096", + "templateHash": "15885562612097082245" }, "name": "Public DNS Zone CNAME record", "description": "This module deploys a Public DNS Zone CNAME record.", diff --git a/avm/res/network/dns-zone/main.bicep b/avm/res/network/dns-zone/main.bicep index 6ecf1f7df9..d0f7457dd2 100644 --- a/avm/res/network/dns-zone/main.bicep +++ b/avm/res/network/dns-zone/main.bicep @@ -54,35 +54,60 @@ param enableTelemetry bool = true var 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') + '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') + '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') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-dnszone.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-dnszone.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource dnsZone 'Microsoft.Network/dnsZones@2018-05-01' = { name: name @@ -93,151 +118,180 @@ resource dnsZone 'Microsoft.Network/dnsZones@2018-05-01' = { } } -module dnsZone_A 'a/main.bicep' = [for (aRecord, index) in (a ?? []): { - name: '${uniqueString(deployment().name, location)}-dnsZone-ARecord-${index}' - params: { - dnsZoneName: dnsZone.name - name: aRecord.name - aRecords: aRecord.?aRecords - metadata: aRecord.?metadata - ttl: aRecord.?ttl ?? 3600 - targetResourceId: aRecord.?targetResourceId - roleAssignments: aRecord.?roleAssignments +module dnsZone_A 'a/main.bicep' = [ + for (aRecord, index) in (a ?? []): { + name: '${uniqueString(deployment().name, location)}-dnsZone-ARecord-${index}' + params: { + dnsZoneName: dnsZone.name + name: aRecord.name + aRecords: aRecord.?aRecords + metadata: aRecord.?metadata + ttl: aRecord.?ttl ?? 3600 + targetResourceId: aRecord.?targetResourceId + roleAssignments: aRecord.?roleAssignments + } } -}] - -module dnsZone_AAAA 'aaaa/main.bicep' = [for (aaaaRecord, index) in (aaaa ?? []): { - name: '${uniqueString(deployment().name, location)}-dnsZone-AAAARecord-${index}' - params: { - dnsZoneName: dnsZone.name - name: aaaaRecord.name - aaaaRecords: aaaaRecord.?aaaaRecords - metadata: aaaaRecord.?metadata - ttl: aaaaRecord.?ttl ?? 3600 - targetResourceId: aaaaRecord.?targetResourceId - roleAssignments: aaaaRecord.?roleAssignments +] + +module dnsZone_AAAA 'aaaa/main.bicep' = [ + for (aaaaRecord, index) in (aaaa ?? []): { + name: '${uniqueString(deployment().name, location)}-dnsZone-AAAARecord-${index}' + params: { + dnsZoneName: dnsZone.name + name: aaaaRecord.name + aaaaRecords: aaaaRecord.?aaaaRecords + metadata: aaaaRecord.?metadata + ttl: aaaaRecord.?ttl ?? 3600 + targetResourceId: aaaaRecord.?targetResourceId + roleAssignments: aaaaRecord.?roleAssignments + } } -}] - -module dnsZone_CNAME 'cname/main.bicep' = [for (cnameRecord, index) in (cname ?? []): { - name: '${uniqueString(deployment().name, location)}-dnsZone-CNAMERecord-${index}' - params: { - dnsZoneName: dnsZone.name - name: cnameRecord.name - cnameRecord: cnameRecord.?cnameRecord - metadata: cnameRecord.?metadata - ttl: cnameRecord.?ttl ?? 3600 - targetResourceId: cnameRecord.?targetResourceId - roleAssignments: cnameRecord.?roleAssignments +] + +module dnsZone_CNAME 'cname/main.bicep' = [ + for (cnameRecord, index) in (cname ?? []): { + name: '${uniqueString(deployment().name, location)}-dnsZone-CNAMERecord-${index}' + params: { + dnsZoneName: dnsZone.name + name: cnameRecord.name + cnameRecord: cnameRecord.?cnameRecord + metadata: cnameRecord.?metadata + ttl: cnameRecord.?ttl ?? 3600 + targetResourceId: cnameRecord.?targetResourceId + roleAssignments: cnameRecord.?roleAssignments + } } -}] - -module dnsZone_CAA 'caa/main.bicep' = [for (caaRecord, index) in (caa ?? []): { - name: '${uniqueString(deployment().name, location)}-dnsZone-CAARecord-${index}' - params: { - dnsZoneName: dnsZone.name - name: caaRecord.name - metadata: caaRecord.?metadata - caaRecords: caaRecord.?caaRecords - ttl: caaRecord.?ttl ?? 3600 - roleAssignments: caaRecord.?roleAssignments +] + +module dnsZone_CAA 'caa/main.bicep' = [ + for (caaRecord, index) in (caa ?? []): { + name: '${uniqueString(deployment().name, location)}-dnsZone-CAARecord-${index}' + params: { + dnsZoneName: dnsZone.name + name: caaRecord.name + metadata: caaRecord.?metadata + caaRecords: caaRecord.?caaRecords + ttl: caaRecord.?ttl ?? 3600 + roleAssignments: caaRecord.?roleAssignments + } } -}] - -module dnsZone_MX 'mx/main.bicep' = [for (mxRecord, index) in (mx ?? []): { - name: '${uniqueString(deployment().name, location)}-dnsZone-MXRecord-${index}' - params: { - dnsZoneName: dnsZone.name - name: mxRecord.name - metadata: mxRecord.?metadata - mxRecords: mxRecord.?mxRecords - ttl: mxRecord.?ttl ?? 3600 - roleAssignments: mxRecord.?roleAssignments +] + +module dnsZone_MX 'mx/main.bicep' = [ + for (mxRecord, index) in (mx ?? []): { + name: '${uniqueString(deployment().name, location)}-dnsZone-MXRecord-${index}' + params: { + dnsZoneName: dnsZone.name + name: mxRecord.name + metadata: mxRecord.?metadata + mxRecords: mxRecord.?mxRecords + ttl: mxRecord.?ttl ?? 3600 + roleAssignments: mxRecord.?roleAssignments + } } -}] - -module dnsZone_NS 'ns/main.bicep' = [for (nsRecord, index) in (ns ?? []): { - name: '${uniqueString(deployment().name, location)}-dnsZone-NSRecord-${index}' - params: { - dnsZoneName: dnsZone.name - name: nsRecord.name - metadata: nsRecord.?metadata - nsRecords: nsRecord.?nsRecords - ttl: nsRecord.?ttl ?? 3600 - roleAssignments: nsRecord.?roleAssignments +] + +module dnsZone_NS 'ns/main.bicep' = [ + for (nsRecord, index) in (ns ?? []): { + name: '${uniqueString(deployment().name, location)}-dnsZone-NSRecord-${index}' + params: { + dnsZoneName: dnsZone.name + name: nsRecord.name + metadata: nsRecord.?metadata + nsRecords: nsRecord.?nsRecords + ttl: nsRecord.?ttl ?? 3600 + roleAssignments: nsRecord.?roleAssignments + } } -}] - -module dnsZone_PTR 'ptr/main.bicep' = [for (ptrRecord, index) in (ptr ?? []): { - name: '${uniqueString(deployment().name, location)}-dnsZone-PTRRecord-${index}' - params: { - dnsZoneName: dnsZone.name - name: ptrRecord.name - metadata: ptrRecord.?metadata - ptrRecords: ptrRecord.?ptrRecords - ttl: ptrRecord.?ttl ?? 3600 - roleAssignments: ptrRecord.?roleAssignments +] + +module dnsZone_PTR 'ptr/main.bicep' = [ + for (ptrRecord, index) in (ptr ?? []): { + name: '${uniqueString(deployment().name, location)}-dnsZone-PTRRecord-${index}' + params: { + dnsZoneName: dnsZone.name + name: ptrRecord.name + metadata: ptrRecord.?metadata + ptrRecords: ptrRecord.?ptrRecords + ttl: ptrRecord.?ttl ?? 3600 + roleAssignments: ptrRecord.?roleAssignments + } } -}] - -module dnsZone_SOA 'soa/main.bicep' = [for (soaRecord, index) in (soa ?? []): { - name: '${uniqueString(deployment().name, location)}-dnsZone-SOARecord-${index}' - params: { - dnsZoneName: dnsZone.name - name: soaRecord.name - metadata: soaRecord.?metadata - soaRecord: soaRecord.?soaRecord - ttl: soaRecord.?ttl ?? 3600 - roleAssignments: soaRecord.?roleAssignments +] + +module dnsZone_SOA 'soa/main.bicep' = [ + for (soaRecord, index) in (soa ?? []): { + name: '${uniqueString(deployment().name, location)}-dnsZone-SOARecord-${index}' + params: { + dnsZoneName: dnsZone.name + name: soaRecord.name + metadata: soaRecord.?metadata + soaRecord: soaRecord.?soaRecord + ttl: soaRecord.?ttl ?? 3600 + roleAssignments: soaRecord.?roleAssignments + } } -}] - -module dnsZone_SRV 'srv/main.bicep' = [for (srvRecord, index) in (srv ?? []): { - name: '${uniqueString(deployment().name, location)}-dnsZone-SRVRecord-${index}' - params: { - dnsZoneName: dnsZone.name - name: srvRecord.name - metadata: srvRecord.?metadata - srvRecords: srvRecord.?srvRecords - ttl: srvRecord.?ttl ?? 3600 - roleAssignments: srvRecord.?roleAssignments +] + +module dnsZone_SRV 'srv/main.bicep' = [ + for (srvRecord, index) in (srv ?? []): { + name: '${uniqueString(deployment().name, location)}-dnsZone-SRVRecord-${index}' + params: { + dnsZoneName: dnsZone.name + name: srvRecord.name + metadata: srvRecord.?metadata + srvRecords: srvRecord.?srvRecords + ttl: srvRecord.?ttl ?? 3600 + roleAssignments: srvRecord.?roleAssignments + } } -}] - -module dnsZone_TXT 'txt/main.bicep' = [for (txtRecord, index) in (txt ?? []): { - name: '${uniqueString(deployment().name, location)}-dnsZone-TXTRecord-${index}' - params: { - dnsZoneName: dnsZone.name - name: txtRecord.name - metadata: txtRecord.?metadata - txtRecords: txtRecord.?txtRecords - ttl: txtRecord.?ttl ?? 3600 - roleAssignments: txtRecord.?roleAssignments +] + +module dnsZone_TXT 'txt/main.bicep' = [ + for (txtRecord, index) in (txt ?? []): { + name: '${uniqueString(deployment().name, location)}-dnsZone-TXTRecord-${index}' + params: { + dnsZoneName: dnsZone.name + name: txtRecord.name + metadata: txtRecord.?metadata + txtRecords: txtRecord.?txtRecords + ttl: txtRecord.?ttl ?? 3600 + roleAssignments: txtRecord.?roleAssignments + } } -}] - -resource dnsZone_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.' +] + +resource dnsZone_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: dnsZone } - scope: dnsZone -} -resource dnsZone_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(dnsZone.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource dnsZone_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(dnsZone.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: dnsZone } - scope: dnsZone -}] +] @description('The resource group the DNS zone was deployed into.') output resourceGroupName string = resourceGroup().name diff --git a/avm/res/network/dns-zone/main.json b/avm/res/network/dns-zone/main.json index e13f76988d..86c01a0ee2 100644 --- a/avm/res/network/dns-zone/main.json +++ b/avm/res/network/dns-zone/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17409480183805156141" + "version": "0.26.54.24096", + "templateHash": "5460415630390016975" }, "name": "Public DNS Zones", "description": "This module deploys a Public DNS zone.", @@ -343,8 +343,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "1014861232584705848" + "version": "0.26.54.24096", + "templateHash": "4017689599365774964" }, "name": "Public DNS Zone A record", "description": "This module deploys a Public DNS Zone A record.", @@ -597,8 +597,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17816545426283561774" + "version": "0.26.54.24096", + "templateHash": "3971171413214558899" }, "name": "Public DNS Zone AAAA record", "description": "This module deploys a Public DNS Zone AAAA record.", @@ -851,8 +851,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11680687850109857660" + "version": "0.26.54.24096", + "templateHash": "15885562612097082245" }, "name": "Public DNS Zone CNAME record", "description": "This module deploys a Public DNS Zone CNAME record.", @@ -1102,8 +1102,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2222693701620961150" + "version": "0.26.54.24096", + "templateHash": "8677073922032532586" }, "name": "Public DNS Zone CAA record", "description": "This module deploys a Public DNS Zone CAA record.", @@ -1345,8 +1345,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11629556138650955144" + "version": "0.26.54.24096", + "templateHash": "1672903557888274249" }, "name": "Public DNS Zone MX record", "description": "This module deploys a Public DNS Zone MX record.", @@ -1588,8 +1588,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16161487720425898744" + "version": "0.26.54.24096", + "templateHash": "18007510262177950674" }, "name": "Public DNS Zone NS record", "description": "This module deploys a Public DNS Zone NS record.", @@ -1831,8 +1831,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "7707819456897162158" + "version": "0.26.54.24096", + "templateHash": "9399981109957572409" }, "name": "Public DNS Zone PTR record", "description": "This module deploys a Public DNS Zone PTR record.", @@ -2074,8 +2074,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4795044712963544053" + "version": "0.26.54.24096", + "templateHash": "7972019384779517121" }, "name": "Public DNS Zone SOA record", "description": "This module deploys a Public DNS Zone SOA record.", @@ -2317,8 +2317,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14428108443514495816" + "version": "0.26.54.24096", + "templateHash": "11464779884101617586" }, "name": "Public DNS Zone SRV record", "description": "This module deploys a Public DNS Zone SRV record.", @@ -2560,8 +2560,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "789212919897780335" + "version": "0.26.54.24096", + "templateHash": "8936268371142649378" }, "name": "Public DNS Zone TXT record", "description": "This module deploys a Public DNS Zone TXT record.", diff --git a/avm/res/network/dns-zone/mx/main.bicep b/avm/res/network/dns-zone/mx/main.bicep index 386b4c254a..758fd767d1 100644 --- a/avm/res/network/dns-zone/mx/main.bicep +++ b/avm/res/network/dns-zone/mx/main.bicep @@ -22,16 +22,40 @@ param roleAssignments roleAssignmentType var 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') + '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') + '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') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } resource dnsZone 'Microsoft.Network/dnsZones@2018-05-01' existing = { @@ -48,19 +72,25 @@ resource MX 'Microsoft.Network/dnsZones/MX@2018-05-01' = { } } -resource MX_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(MX.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource MX_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(MX.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: MX } - scope: MX -}] +] @description('The name of the deployed MX record.') output name string = MX.name diff --git a/avm/res/network/dns-zone/mx/main.json b/avm/res/network/dns-zone/mx/main.json index fcf04baf23..36bfc0b0ee 100644 --- a/avm/res/network/dns-zone/mx/main.json +++ b/avm/res/network/dns-zone/mx/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11629556138650955144" + "version": "0.26.54.24096", + "templateHash": "1672903557888274249" }, "name": "Public DNS Zone MX record", "description": "This module deploys a Public DNS Zone MX record.", diff --git a/avm/res/network/dns-zone/ns/main.bicep b/avm/res/network/dns-zone/ns/main.bicep index 7e1964d6fd..3e4cbe4f40 100644 --- a/avm/res/network/dns-zone/ns/main.bicep +++ b/avm/res/network/dns-zone/ns/main.bicep @@ -22,16 +22,40 @@ param roleAssignments roleAssignmentType var 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') + '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') + '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') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } resource dnsZone 'Microsoft.Network/dnsZones@2018-05-01' existing = { name: dnsZoneName @@ -47,19 +71,25 @@ resource NS 'Microsoft.Network/dnsZones/NS@2018-05-01' = { } } -resource NS_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(NS.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource NS_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(NS.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: NS } - scope: NS -}] +] @description('The name of the deployed NS record.') output name string = NS.name diff --git a/avm/res/network/dns-zone/ns/main.json b/avm/res/network/dns-zone/ns/main.json index 46226a0939..f079d87268 100644 --- a/avm/res/network/dns-zone/ns/main.json +++ b/avm/res/network/dns-zone/ns/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16161487720425898744" + "version": "0.26.54.24096", + "templateHash": "18007510262177950674" }, "name": "Public DNS Zone NS record", "description": "This module deploys a Public DNS Zone NS record.", diff --git a/avm/res/network/dns-zone/ptr/main.bicep b/avm/res/network/dns-zone/ptr/main.bicep index 6a2e0a0dd5..a3463a2ce3 100644 --- a/avm/res/network/dns-zone/ptr/main.bicep +++ b/avm/res/network/dns-zone/ptr/main.bicep @@ -22,16 +22,40 @@ param roleAssignments roleAssignmentType var 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') + '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') + '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') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } resource dnsZone 'Microsoft.Network/dnsZones@2018-05-01' existing = { @@ -48,19 +72,25 @@ resource PTR 'Microsoft.Network/dnsZones/PTR@2018-05-01' = { } } -resource PTR_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(PTR.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource PTR_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(PTR.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: PTR } - scope: PTR -}] +] @description('The name of the deployed PTR record.') output name string = PTR.name diff --git a/avm/res/network/dns-zone/ptr/main.json b/avm/res/network/dns-zone/ptr/main.json index cdb6b7f82d..3ffab06b51 100644 --- a/avm/res/network/dns-zone/ptr/main.json +++ b/avm/res/network/dns-zone/ptr/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "7707819456897162158" + "version": "0.26.54.24096", + "templateHash": "9399981109957572409" }, "name": "Public DNS Zone PTR record", "description": "This module deploys a Public DNS Zone PTR record.", diff --git a/avm/res/network/dns-zone/soa/main.bicep b/avm/res/network/dns-zone/soa/main.bicep index b6aea1462b..17eceec692 100644 --- a/avm/res/network/dns-zone/soa/main.bicep +++ b/avm/res/network/dns-zone/soa/main.bicep @@ -22,16 +22,40 @@ param roleAssignments roleAssignmentType var 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') + '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') + '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') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } resource dnsZone 'Microsoft.Network/dnsZones@2018-05-01' existing = { @@ -48,19 +72,25 @@ resource SOA 'Microsoft.Network/dnsZones/SOA@2018-05-01' = { } } -resource SOA_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(SOA.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource SOA_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(SOA.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: SOA } - scope: SOA -}] +] @description('The name of the deployed SOA record.') output name string = SOA.name diff --git a/avm/res/network/dns-zone/soa/main.json b/avm/res/network/dns-zone/soa/main.json index 8b0dd53fa1..15636237ab 100644 --- a/avm/res/network/dns-zone/soa/main.json +++ b/avm/res/network/dns-zone/soa/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4795044712963544053" + "version": "0.26.54.24096", + "templateHash": "7972019384779517121" }, "name": "Public DNS Zone SOA record", "description": "This module deploys a Public DNS Zone SOA record.", diff --git a/avm/res/network/dns-zone/srv/main.bicep b/avm/res/network/dns-zone/srv/main.bicep index 83b4ca435d..4250514384 100644 --- a/avm/res/network/dns-zone/srv/main.bicep +++ b/avm/res/network/dns-zone/srv/main.bicep @@ -22,16 +22,40 @@ param roleAssignments roleAssignmentType var 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') + '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') + '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') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } resource dnsZone 'Microsoft.Network/dnsZones@2018-05-01' existing = { name: dnsZoneName @@ -47,19 +71,25 @@ resource SRV 'Microsoft.Network/dnsZones/SRV@2018-05-01' = { } } -resource SRV_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(SRV.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource SRV_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(SRV.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: SRV } - scope: SRV -}] +] @description('The name of the deployed SRV record.') output name string = SRV.name diff --git a/avm/res/network/dns-zone/srv/main.json b/avm/res/network/dns-zone/srv/main.json index 56e32bec1e..1ed4aab75e 100644 --- a/avm/res/network/dns-zone/srv/main.json +++ b/avm/res/network/dns-zone/srv/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14428108443514495816" + "version": "0.26.54.24096", + "templateHash": "11464779884101617586" }, "name": "Public DNS Zone SRV record", "description": "This module deploys a Public DNS Zone SRV record.", diff --git a/avm/res/network/dns-zone/tests/e2e/defaults/main.test.bicep b/avm/res/network/dns-zone/tests/e2e/defaults/main.test.bicep index 7c97b1e101..41d0b58231 100644 --- a/avm/res/network/dns-zone/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/dns-zone/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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.com' - location: 'global' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001.com' + location: 'global' + } } -}] +] diff --git a/avm/res/network/dns-zone/tests/e2e/max/dependencies.bicep b/avm/res/network/dns-zone/tests/e2e/max/dependencies.bicep index 22bd417624..8f0e73eebf 100644 --- a/avm/res/network/dns-zone/tests/e2e/max/dependencies.bicep +++ b/avm/res/network/dns-zone/tests/e2e/max/dependencies.bicep @@ -8,26 +8,26 @@ param trafficManagerProfileName string param managedIdentityName string resource trafficManagerProfile 'Microsoft.Network/trafficmanagerprofiles@2022-04-01-preview' = { - name: trafficManagerProfileName - location: 'global' - properties: { - trafficRoutingMethod: 'Performance' - maxReturn: 0 - dnsConfig: { - relativeName: trafficManagerProfileName - ttl: 60 - } - monitorConfig: { - protocol: 'HTTP' - port: 80 - path: '/' - } + name: trafficManagerProfileName + location: 'global' + properties: { + trafficRoutingMethod: 'Performance' + maxReturn: 0 + dnsConfig: { + relativeName: trafficManagerProfileName + ttl: 60 } + monitorConfig: { + protocol: 'HTTP' + port: 80 + path: '/' + } + } } resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The resource ID of the created Traffic Manager Profile.') diff --git a/avm/res/network/dns-zone/tests/e2e/max/main.test.bicep b/avm/res/network/dns-zone/tests/e2e/max/main.test.bicep index a7827f4d55..b86e5b815f 100644 --- a/avm/res/network/dns-zone/tests/e2e/max/main.test.bicep +++ b/avm/res/network/dns-zone/tests/e2e/max/main.test.bicep @@ -46,256 +46,282 @@ 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.com' - location: 'global' - a: [ - { - aRecords: [ - { - ipv4Address: '10.240.4.4' - } - ] - name: 'A_10.240.4.4' - 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' - } - ] - ttl: 3600 - } - ] - aaaa: [ - { - aaaaRecords: [ - { - ipv6Address: '2001:0db8:85a3:0000:0000:8a2e:0370:7334' - } - ] - name: 'AAAA_2001_0db8_85a3_0000_0000_8a2e_0370_7334' - ttl: 3600 - } - ] - cname: [ - { - cnameRecord: { - cname: 'test' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001.com' + location: 'global' + a: [ + { + aRecords: [ + { + ipv4Address: '10.240.4.4' + } + ] + name: 'A_10.240.4.4' + 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' + } + ] + ttl: 3600 } - name: 'CNAME_test' - 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' - } - ] - ttl: 3600 - } - { - name: 'CNAME_aliasRecordSet' - targetResourceId: nestedDependencies.outputs.trafficManagerProfileResourceId - } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - mx: [ - { - mxRecords: [ - { - exchange: 'contoso.com' - preference: 100 - } - ] - name: 'MX_contoso' - 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' - } - ] - ttl: 3600 - } - ] - ptr: [ - { - name: 'PTR_contoso' - ptrRecords: [ - { - ptrdname: 'contoso.com' - } - ] - 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' - } - ] - ttl: 3600 - } - ] - 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' - } - ] - soa: [ - { - name: '@' - 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' - } - ] - soaRecord: { - email: 'azuredns-hostmaster.microsoft.com' - expireTime: 2419200 - host: 'ns1-04.azure-dns.com.' - minimumTtl: 300 - refreshTime: 3600 - retryTime: 300 - serialNumber: '1' + ] + aaaa: [ + { + aaaaRecords: [ + { + ipv6Address: '2001:0db8:85a3:0000:0000:8a2e:0370:7334' + } + ] + name: 'AAAA_2001_0db8_85a3_0000_0000_8a2e_0370_7334' + ttl: 3600 } - ttl: 3600 - } - ] - srv: [ - { - name: 'SRV_contoso' - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + ] + cname: [ + { + cnameRecord: { + cname: 'test' } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - ] - srvRecords: [ - { - port: 9332 - priority: 0 - target: 'test.contoso.com' - weight: 0 - } - ] - ttl: 3600 + name: 'CNAME_test' + 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' + } + ] + ttl: 3600 + } + { + name: 'CNAME_aliasRecordSet' + targetResourceId: nestedDependencies.outputs.trafficManagerProfileResourceId + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - txt: [ - { - name: 'TXT_test' - 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' - } - ] - ttl: 3600 - txtRecords: [ - { - value: [ - 'test' - ] + mx: [ + { + mxRecords: [ + { + exchange: 'contoso.com' + preference: 100 + } + ] + name: 'MX_contoso' + 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' + } + ] + ttl: 3600 + } + ] + ptr: [ + { + name: 'PTR_contoso' + ptrRecords: [ + { + ptrdname: 'contoso.com' + } + ] + 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' + } + ] + ttl: 3600 + } + ] + 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' + } + ] + soa: [ + { + name: '@' + 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' + } + ] + soaRecord: { + email: 'azuredns-hostmaster.microsoft.com' + expireTime: 2419200 + host: 'ns1-04.azure-dns.com.' + minimumTtl: 300 + refreshTime: 3600 + retryTime: 300 + serialNumber: '1' } - ] + ttl: 3600 + } + ] + srv: [ + { + name: 'SRV_contoso' + 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' + } + ] + srvRecords: [ + { + port: 9332 + priority: 0 + target: 'test.contoso.com' + weight: 0 + } + ] + ttl: 3600 + } + ] + txt: [ + { + name: 'TXT_test' + 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' + } + ] + ttl: 3600 + txtRecords: [ + { + value: [ + 'test' + ] + } + ] + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/network/dns-zone/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/network/dns-zone/tests/e2e/waf-aligned/dependencies.bicep index 22bd417624..8f0e73eebf 100644 --- a/avm/res/network/dns-zone/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/network/dns-zone/tests/e2e/waf-aligned/dependencies.bicep @@ -8,26 +8,26 @@ param trafficManagerProfileName string param managedIdentityName string resource trafficManagerProfile 'Microsoft.Network/trafficmanagerprofiles@2022-04-01-preview' = { - name: trafficManagerProfileName - location: 'global' - properties: { - trafficRoutingMethod: 'Performance' - maxReturn: 0 - dnsConfig: { - relativeName: trafficManagerProfileName - ttl: 60 - } - monitorConfig: { - protocol: 'HTTP' - port: 80 - path: '/' - } + name: trafficManagerProfileName + location: 'global' + properties: { + trafficRoutingMethod: 'Performance' + maxReturn: 0 + dnsConfig: { + relativeName: trafficManagerProfileName + ttl: 60 } + monitorConfig: { + protocol: 'HTTP' + port: 80 + path: '/' + } + } } resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The resource ID of the created Traffic Manager Profile.') diff --git a/avm/res/network/dns-zone/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/dns-zone/tests/e2e/waf-aligned/main.test.bicep index a3d821e933..fa23869633 100644 --- a/avm/res/network/dns-zone/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/dns-zone/tests/e2e/waf-aligned/main.test.bicep @@ -46,20 +46,22 @@ 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.com' - location: 'global' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001.com' + location: 'global' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } } -}] +] diff --git a/avm/res/network/dns-zone/txt/main.bicep b/avm/res/network/dns-zone/txt/main.bicep index 225c8baf68..2477ee357e 100644 --- a/avm/res/network/dns-zone/txt/main.bicep +++ b/avm/res/network/dns-zone/txt/main.bicep @@ -22,16 +22,40 @@ param roleAssignments roleAssignmentType var 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') + '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') + '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') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } resource dnsZone 'Microsoft.Network/dnsZones@2018-05-01' existing = { name: dnsZoneName @@ -47,19 +71,25 @@ resource TXT 'Microsoft.Network/dnsZones/TXT@2018-05-01' = { } } -resource TXT_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(TXT.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource TXT_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(TXT.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: TXT } - scope: TXT -}] +] @description('The name of the deployed TXT record.') output name string = TXT.name diff --git a/avm/res/network/dns-zone/txt/main.json b/avm/res/network/dns-zone/txt/main.json index 0d275f47ee..16576f7f7c 100644 --- a/avm/res/network/dns-zone/txt/main.json +++ b/avm/res/network/dns-zone/txt/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "789212919897780335" + "version": "0.26.54.24096", + "templateHash": "8936268371142649378" }, "name": "Public DNS Zone TXT record", "description": "This module deploys a Public DNS Zone TXT record.", diff --git a/avm/res/network/express-route-circuit/main.bicep b/avm/res/network/express-route-circuit/main.bicep index 1394cacf99..20107ec0ec 100644 --- a/avm/res/network/express-route-circuit/main.bicep +++ b/avm/res/network/express-route-circuit/main.bicep @@ -87,30 +87,40 @@ param enableTelemetry bool = true var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + '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') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-expressroutecircuit.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-expressroutecircuit.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource expressRouteCircuits 'Microsoft.Network/expressRouteCircuits@2023-04-01' = { name: name @@ -125,75 +135,94 @@ resource expressRouteCircuits 'Microsoft.Network/expressRouteCircuits@2023-04-01 allowClassicOperations: allowClassicOperations globalReachEnabled: globalReachEnabled bandwidthInGbps: bandwidthInGbps != 0 ? bandwidthInGbps : null - expressRoutePort: !empty(expressRoutePortResourceId) ? { - id: expressRoutePortResourceId - } : null + expressRoutePort: !empty(expressRoutePortResourceId) + ? { + id: expressRoutePortResourceId + } + : null serviceProviderProperties: { serviceProviderName: serviceProviderName peeringLocation: peeringLocation bandwidthInMbps: bandwidthInMbps } - peerings: peering ? [ - { - name: peeringType - properties: { - peeringType: peeringType - sharedKey: sharedKey - peerASN: peerASN - primaryPeerAddressPrefix: primaryPeerAddressPrefix - secondaryPeerAddressPrefix: secondaryPeerAddressPrefix - vlanId: vlanId - } - } - ] : null + peerings: peering + ? [ + { + name: peeringType + properties: { + peeringType: peeringType + sharedKey: sharedKey + peerASN: peerASN + primaryPeerAddressPrefix: primaryPeerAddressPrefix + secondaryPeerAddressPrefix: secondaryPeerAddressPrefix + vlanId: vlanId + } + } + ] + : null } } -resource expressRouteCircuits_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.' +resource expressRouteCircuits_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: expressRouteCircuits } - scope: expressRouteCircuits -} -resource expressRouteCircuits_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource expressRouteCircuits_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: expressRouteCircuits } - scope: expressRouteCircuits -}] - -resource expressRouteCircuits_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(expressRouteCircuits.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +] + +resource expressRouteCircuits_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(expressRouteCircuits.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: expressRouteCircuits } - scope: expressRouteCircuits -}] +] @description('The resource ID of express route curcuit.') output resourceId string = expressRouteCircuits.id diff --git a/avm/res/network/express-route-circuit/main.json b/avm/res/network/express-route-circuit/main.json index d1deecbc00..4f030b9351 100644 --- a/avm/res/network/express-route-circuit/main.json +++ b/avm/res/network/express-route-circuit/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "1951233357364145060" + "version": "0.26.54.24096", + "templateHash": "12576570459858721920" }, "name": "ExpressRoute Circuits", "description": "This module deploys an Express Route Circuit.", diff --git a/avm/res/network/express-route-circuit/tests/e2e/defaults/main.test.bicep b/avm/res/network/express-route-circuit/tests/e2e/defaults/main.test.bicep index 27ad16cd30..8d241b905b 100644 --- a/avm/res/network/express-route-circuit/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/express-route-circuit/tests/e2e/defaults/main.test.bicep @@ -36,14 +36,16 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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' - bandwidthInMbps: 50 - peeringLocation: 'Amsterdam' - serviceProviderName: 'Equinix' - location: resourceLocation +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + bandwidthInMbps: 50 + peeringLocation: 'Amsterdam' + serviceProviderName: 'Equinix' + location: resourceLocation + } } -}] +] diff --git a/avm/res/network/express-route-circuit/tests/e2e/max/dependencies.bicep b/avm/res/network/express-route-circuit/tests/e2e/max/dependencies.bicep index a7f42aee7b..7be39e253a 100644 --- a/avm/res/network/express-route-circuit/tests/e2e/max/dependencies.bicep +++ b/avm/res/network/express-route-circuit/tests/e2e/max/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/network/express-route-circuit/tests/e2e/max/main.test.bicep b/avm/res/network/express-route-circuit/tests/e2e/max/main.test.bicep index fbe38c7edd..56e3591e91 100644 --- a/avm/res/network/express-route-circuit/tests/e2e/max/main.test.bicep +++ b/avm/res/network/express-route-circuit/tests/e2e/max/main.test.bicep @@ -58,58 +58,63 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t // 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 - bandwidthInMbps: 50 - peeringLocation: 'Amsterdam' - serviceProviderName: 'Equinix' - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +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 + bandwidthInMbps: 50 + peeringLocation: 'Amsterdam' + serviceProviderName: 'Equinix' + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + 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' + } + ] + skuFamily: 'MeteredData' + skuTier: 'Standard' + allowClassicOperations: true + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - skuFamily: 'MeteredData' - skuTier: 'Standard' - allowClassicOperations: true - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [nestedDependencies] } - dependsOn: [ nestedDependencies ] -}] +] diff --git a/avm/res/network/express-route-circuit/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/network/express-route-circuit/tests/e2e/waf-aligned/dependencies.bicep index a7f42aee7b..7be39e253a 100644 --- a/avm/res/network/express-route-circuit/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/network/express-route-circuit/tests/e2e/waf-aligned/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/network/express-route-circuit/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/express-route-circuit/tests/e2e/waf-aligned/main.test.bicep index bd5b28139a..cc8f20a1d2 100644 --- a/avm/res/network/express-route-circuit/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/express-route-circuit/tests/e2e/waf-aligned/main.test.bicep @@ -58,40 +58,42 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t // 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 - bandwidthInMbps: 50 - peeringLocation: 'Amsterdam' - serviceProviderName: 'Equinix' - 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 + bandwidthInMbps: 50 + peeringLocation: 'Amsterdam' + serviceProviderName: 'Equinix' + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + skuFamily: 'MeteredData' + skuTier: 'Standard' + allowClassicOperations: true + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - skuFamily: 'MeteredData' - skuTier: 'Standard' - allowClassicOperations: true - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/network/express-route-gateway/main.bicep b/avm/res/network/express-route-gateway/main.bicep index 681e2e9fe7..2dfda0cf5d 100644 --- a/avm/res/network/express-route-gateway/main.bicep +++ b/avm/res/network/express-route-gateway/main.bicep @@ -37,30 +37,40 @@ param lock lockType var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + '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') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-expressroutegateway.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-expressroutegateway.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource expressRouteGateway 'Microsoft.Network/expressRouteGateways@2023-04-01' = { name: name @@ -81,28 +91,37 @@ resource expressRouteGateway 'Microsoft.Network/expressRouteGateways@2023-04-01' } } -resource expressRouteGateway_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.' +resource expressRouteGateway_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: expressRouteGateway } - scope: expressRouteGateway -} -resource expressRouteGateway_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(expressRouteGateway.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource expressRouteGateway_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(expressRouteGateway.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: expressRouteGateway } - scope: expressRouteGateway -}] +] @description('The resource ID of the ExpressRoute Gateway.') output resourceId string = expressRouteGateway.id diff --git a/avm/res/network/express-route-gateway/main.json b/avm/res/network/express-route-gateway/main.json index 2c4afb55c3..08858bc019 100644 --- a/avm/res/network/express-route-gateway/main.json +++ b/avm/res/network/express-route-gateway/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "5520177504222517638" + "version": "0.26.54.24096", + "templateHash": "7886944632822822023" }, "name": "Express Route Gateways", "description": "This module deploys an Express Route Gateway.", diff --git a/avm/res/network/express-route-gateway/tests/e2e/max/main.test.bicep b/avm/res/network/express-route-gateway/tests/e2e/max/main.test.bicep index 22b0539525..110c5a0026 100644 --- a/avm/res/network/express-route-gateway/tests/e2e/max/main.test.bicep +++ b/avm/res/network/express-route-gateway/tests/e2e/max/main.test.bicep @@ -74,7 +74,10 @@ module testDeployment '../../../main.bicep' = { principalType: 'ServicePrincipal' } { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) principalId: nestedDependencies.outputs.managedIdentityPrincipalId principalType: 'ServicePrincipal' } diff --git a/avm/res/network/firewall-policy/main.bicep b/avm/res/network/firewall-policy/main.bicep index dfefd95117..5da990e5c2 100644 --- a/avm/res/network/firewall-policy/main.bicep +++ b/avm/res/network/firewall-policy/main.bicep @@ -97,30 +97,37 @@ param enableTelemetry bool = true @description('Optional. Rule collection groups.') param ruleCollectionGroups array? -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: 'UserAssigned' - userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null -} : null - -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-firewallpolicy.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +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: 'UserAssigned' + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null + } + : null + +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-firewallpolicy.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource firewallPolicy 'Microsoft.Network/firewallPolicies@2023-04-01' = { name: name @@ -128,37 +135,47 @@ resource firewallPolicy 'Microsoft.Network/firewallPolicies@2023-04-01' = { tags: tags identity: identity properties: { - basePolicy: !empty(basePolicyResourceId ?? '') ? { - id: basePolicyResourceId - } : null - dnsSettings: enableProxy ? { - enableProxy: enableProxy - servers: servers ?? [] - } : null - insights: insightsIsEnabled ? { - isEnabled: insightsIsEnabled - logAnalyticsResources: { - defaultWorkspaceId: { - id: defaultWorkspaceId + basePolicy: !empty(basePolicyResourceId ?? '') + ? { + id: basePolicyResourceId } - workspaces: workspaces - } - retentionDays: retentionDays - } : null - intrusionDetection: (mode != 'Off') ? { - configuration: { - bypassTrafficSettings: bypassTrafficSettings - signatureOverrides: signatureOverrides - } - mode: mode - } : null + : null + dnsSettings: enableProxy + ? { + enableProxy: enableProxy + servers: servers ?? [] + } + : null + insights: insightsIsEnabled + ? { + isEnabled: insightsIsEnabled + logAnalyticsResources: { + defaultWorkspaceId: { + id: defaultWorkspaceId + } + workspaces: workspaces + } + retentionDays: retentionDays + } + : null + intrusionDetection: (mode != 'Off') + ? { + configuration: { + bypassTrafficSettings: bypassTrafficSettings + signatureOverrides: signatureOverrides + } + mode: mode + } + : null sku: { tier: tier } - snat: !empty(privateRanges) ? { - autoLearnPrivateRanges: autoLearnPrivateRanges - privateRanges: privateRanges - } : null + snat: !empty(privateRanges) + ? { + autoLearnPrivateRanges: autoLearnPrivateRanges + privateRanges: privateRanges + } + : null sql: { allowSqlRedirect: allowSqlRedirect } @@ -167,12 +184,14 @@ resource firewallPolicy 'Microsoft.Network/firewallPolicies@2023-04-01' = { fqdns: fqdns ?? [] ipAddresses: ipAddresses ?? [] } - transportSecurity: (!empty(keyVaultSecretId ?? []) || !empty(certificateName ?? '')) ? { - certificateAuthority: { - keyVaultSecretId: keyVaultSecretId - name: certificateName - } - } : null + transportSecurity: (!empty(keyVaultSecretId ?? []) || !empty(certificateName ?? '')) + ? { + certificateAuthority: { + keyVaultSecretId: keyVaultSecretId + name: certificateName + } + } + : null } } @@ -181,15 +200,17 @@ resource firewallPolicy 'Microsoft.Network/firewallPolicies@2023-04-01' = { // because of concurrent access to the base policy. // The next line forces ARM to deploy them one after the other, so no race concition on the base policy will happen. @batchSize(1) -module firewallPolicy_ruleCollectionGroups 'rule-collection-group/main.bicep' = [for (ruleCollectionGroup, index) in (ruleCollectionGroups ?? []): { - name: '${uniqueString(deployment().name, location)}-firewallPolicy_ruleCollectionGroups-${index}' - params: { - firewallPolicyName: firewallPolicy.name - name: ruleCollectionGroup.name - priority: ruleCollectionGroup.priority - ruleCollections: ruleCollectionGroup.ruleCollections +module firewallPolicy_ruleCollectionGroups 'rule-collection-group/main.bicep' = [ + for (ruleCollectionGroup, index) in (ruleCollectionGroups ?? []): { + name: '${uniqueString(deployment().name, location)}-firewallPolicy_ruleCollectionGroups-${index}' + params: { + firewallPolicyName: firewallPolicy.name + name: ruleCollectionGroup.name + priority: ruleCollectionGroup.priority + ruleCollections: ruleCollectionGroup.ruleCollections + } } -}] +] @description('The name of the deployed firewall policy.') output name string = firewallPolicy.name diff --git a/avm/res/network/firewall-policy/main.json b/avm/res/network/firewall-policy/main.json index 7a05153f27..1316a3c93e 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.25.53.49325", - "templateHash": "8352567375549268667" + "version": "0.26.54.24096", + "templateHash": "5451872777085737013" }, "name": "Firewall Policies", "description": "This module deploys a Firewall Policy.", @@ -311,8 +311,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17945865046689186214" + "version": "0.26.54.24096", + "templateHash": "15656278354863511578" }, "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 b6ec7d3e49..8fd8a36653 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.25.53.49325", - "templateHash": "17945865046689186214" + "version": "0.26.54.24096", + "templateHash": "15656278354863511578" }, "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/defaults/main.test.bicep b/avm/res/network/firewall-policy/tests/e2e/defaults/main.test.bicep index c48fbf7ba4..f63c5d678f 100644 --- a/avm/res/network/firewall-policy/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/firewall-policy/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 +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 + } } -}] +] 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 0295a163df..b713f73fbf 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 @@ -45,63 +45,65 @@ 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 - tier: 'Premium' - mode: 'Alert' - ruleCollectionGroups: [ - { - name: '${namePrefix}-rule-001' - priority: 5000 - ruleCollections: [ - { - action: { - type: 'Allow' - } - name: 'collection002' - priority: 5555 - ruleCollectionType: 'FirewallPolicyFilterRuleCollection' - rules: [ - { - destinationAddresses: [ - '*' - ] - destinationFqdns: [] - destinationIpGroups: [] - destinationPorts: [ - '80' - ] - ipProtocols: [ - 'TCP' - 'UDP' - ] - name: 'rule002' - ruleType: 'NetworkRule' - sourceAddresses: [ - '*' - ] - sourceIpGroups: [] +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 + tier: 'Premium' + mode: 'Alert' + ruleCollectionGroups: [ + { + name: '${namePrefix}-rule-001' + priority: 5000 + ruleCollections: [ + { + action: { + type: 'Allow' } - ] - } + name: 'collection002' + priority: 5555 + ruleCollectionType: 'FirewallPolicyFilterRuleCollection' + rules: [ + { + destinationAddresses: [ + '*' + ] + destinationFqdns: [] + destinationIpGroups: [] + destinationPorts: [ + '80' + ] + ipProtocols: [ + 'TCP' + 'UDP' + ] + name: 'rule002' + ruleType: 'NetworkRule' + sourceAddresses: [ + '*' + ] + sourceIpGroups: [] + } + ] + } + ] + } + ] + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId ] } - ] - managedIdentities: { - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + allowSqlRedirect: true + autoLearnPrivateRanges: 'Enabled' } - allowSqlRedirect: true - autoLearnPrivateRanges: 'Enabled' } -}] +] diff --git a/avm/res/network/firewall-policy/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/firewall-policy/tests/e2e/waf-aligned/main.test.bicep index 51003decf8..0462603a72 100644 --- a/avm/res/network/firewall-policy/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/firewall-policy/tests/e2e/waf-aligned/main.test.bicep @@ -36,57 +36,59 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 - ruleCollectionGroups: [ - { - name: '${namePrefix}-rule-001' - priority: 5000 - ruleCollections: [ - { - action: { - type: 'Allow' - } - name: 'collection002' - priority: 5555 - ruleCollectionType: 'FirewallPolicyFilterRuleCollection' - rules: [ - { - destinationAddresses: [ - '*' - ] - destinationFqdns: [] - destinationIpGroups: [] - destinationPorts: [ - '80' - ] - ipProtocols: [ - 'TCP' - 'UDP' - ] - name: 'rule002' - ruleType: 'NetworkRule' - sourceAddresses: [ - '*' - ] - sourceIpGroups: [] +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 + ruleCollectionGroups: [ + { + name: '${namePrefix}-rule-001' + priority: 5000 + ruleCollections: [ + { + action: { + type: 'Allow' } - ] - } - ] + name: 'collection002' + priority: 5555 + ruleCollectionType: 'FirewallPolicyFilterRuleCollection' + rules: [ + { + destinationAddresses: [ + '*' + ] + destinationFqdns: [] + destinationIpGroups: [] + destinationPorts: [ + '80' + ] + ipProtocols: [ + 'TCP' + 'UDP' + ] + name: 'rule002' + ruleType: 'NetworkRule' + sourceAddresses: [ + '*' + ] + sourceIpGroups: [] + } + ] + } + ] + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + allowSqlRedirect: true + autoLearnPrivateRanges: 'Enabled' + threatIntelMode: 'Deny' } - allowSqlRedirect: true - autoLearnPrivateRanges: 'Enabled' - threatIntelMode: 'Deny' } -}] +] diff --git a/avm/res/network/front-door-web-application-firewall-policy/main.bicep b/avm/res/network/front-door-web-application-firewall-policy/main.bicep index d49e672750..8ca355b991 100644 --- a/avm/res/network/front-door-web-application-firewall-policy/main.bicep +++ b/avm/res/network/front-door-web-application-firewall-policy/main.bicep @@ -56,7 +56,7 @@ param customRules object = { matchVariable: 'RemoteAddr' operator: 'GeoMatch' negateCondition: true - matchValue: [ 'ZZ' ] + matchValue: ['ZZ'] } ] } @@ -79,27 +79,34 @@ 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.network-frontdoorwebappfirewallpolicy.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.network-frontdoorwebappfirewallpolicy.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource frontDoorWAFPolicy 'Microsoft.Network/FrontDoorWebApplicationFirewallPolicies@2022-05-01' = { name: name @@ -115,28 +122,37 @@ resource frontDoorWAFPolicy 'Microsoft.Network/FrontDoorWebApplicationFirewallPo } } -resource frontDoorWAFPolicy_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.' +resource frontDoorWAFPolicy_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: frontDoorWAFPolicy } - scope: frontDoorWAFPolicy -} -resource frontDoorWAFPolicy_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(frontDoorWAFPolicy.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource frontDoorWAFPolicy_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(frontDoorWAFPolicy.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: frontDoorWAFPolicy } - scope: frontDoorWAFPolicy -}] +] @description('The name of the Front Door WAF policy.') output name string = frontDoorWAFPolicy.name diff --git a/avm/res/network/front-door-web-application-firewall-policy/main.json b/avm/res/network/front-door-web-application-firewall-policy/main.json index 4df136f697..54f07df7fe 100644 --- a/avm/res/network/front-door-web-application-firewall-policy/main.json +++ b/avm/res/network/front-door-web-application-firewall-policy/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "1373577986476180700" + "version": "0.26.54.24096", + "templateHash": "11803357399151500299" }, "name": "Front Door Web Application Firewall (WAF) Policies", "description": "This module deploys a Front Door Web Application Firewall (WAF) Policy.", diff --git a/avm/res/network/front-door-web-application-firewall-policy/tests/e2e/defaults/main.test.bicep b/avm/res/network/front-door-web-application-firewall-policy/tests/e2e/defaults/main.test.bicep index 92998f86dc..7d35210808 100644 --- a/avm/res/network/front-door-web-application-firewall-policy/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/front-door-web-application-firewall-policy/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { // ============== // @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 +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 + } } -}] +] diff --git a/avm/res/network/front-door-web-application-firewall-policy/tests/e2e/max/main.test.bicep b/avm/res/network/front-door-web-application-firewall-policy/tests/e2e/max/main.test.bicep index e5a2cab892..d79784401c 100644 --- a/avm/res/network/front-door-web-application-firewall-policy/tests/e2e/max/main.test.bicep +++ b/avm/res/network/front-door-web-application-firewall-policy/tests/e2e/max/main.test.bicep @@ -45,100 +45,105 @@ 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 - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - sku: 'Premium_AzureFrontDoor' - policySettings: { - mode: 'Prevention' - redirectUrl: 'http://www.bing.com' - customBlockResponseStatusCode: 200 - customBlockResponseBody: 'PGh0bWw+CjxoZWFkZXI+PHRpdGxlPkhlbGxvPC90aXRsZT48L2hlYWRlcj4KPGJvZHk+CkhlbGxvIHdvcmxkCjwvYm9keT4KPC9odG1sPg==' - } - customRules: { - rules: [ +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 + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + sku: 'Premium_AzureFrontDoor' + policySettings: { + mode: 'Prevention' + redirectUrl: 'http://www.bing.com' + customBlockResponseStatusCode: 200 + customBlockResponseBody: 'PGh0bWw+CjxoZWFkZXI+PHRpdGxlPkhlbGxvPC90aXRsZT48L2hlYWRlcj4KPGJvZHk+CkhlbGxvIHdvcmxkCjwvYm9keT4KPC9odG1sPg==' + } + customRules: { + rules: [ + { + name: 'CustomRule1' + priority: 2 + enabledState: 'Enabled' + action: 'Block' + ruleType: 'MatchRule' + rateLimitDurationInMinutes: 1 + rateLimitThreshold: 10 + matchConditions: [ + { + matchVariable: 'RemoteAddr' + selector: null + operator: 'GeoMatch' + negateCondition: false + transforms: [] + matchValue: [ + 'CH' + ] + } + { + matchVariable: 'RequestHeader' + selector: 'UserAgent' + operator: 'Contains' + negateCondition: false + transforms: [] + matchValue: [ + 'windows' + ] + } + { + matchVariable: 'QueryString' + operator: 'Contains' + negateCondition: false + transforms: [ + 'UrlDecode' + 'Lowercase' + ] + matchValue: [ + '' + ] + } + ] + } + ] + } + managedRules: { + managedRuleSets: [ + { + ruleSetType: 'Microsoft_BotManagerRuleSet' + ruleSetVersion: '1.0' + } + ] + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + roleAssignments: [ { - name: 'CustomRule1' - priority: 2 - enabledState: 'Enabled' - action: 'Block' - ruleType: 'MatchRule' - rateLimitDurationInMinutes: 1 - rateLimitThreshold: 10 - matchConditions: [ - { - matchVariable: 'RemoteAddr' - selector: null - operator: 'GeoMatch' - negateCondition: false - transforms: [] - matchValue: [ - 'CH' - ] - } - { - matchVariable: 'RequestHeader' - selector: 'UserAgent' - operator: 'Contains' - negateCondition: false - transforms: [] - matchValue: [ - 'windows' - ] - } - { - matchVariable: 'QueryString' - operator: 'Contains' - negateCondition: false - transforms: [ - 'UrlDecode' - 'Lowercase' - ] - matchValue: [ - '' - ] - } - ] + roleDefinitionIdOrName: 'Owner' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' } - ] - } - managedRules: { - managedRuleSets: [ { - ruleSetType: 'Microsoft_BotManagerRuleSet' - ruleSetVersion: '1.0' + 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' - Role: 'DeploymentValidation' - } - 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' - } - ] } -}] +] diff --git a/avm/res/network/front-door-web-application-firewall-policy/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/front-door-web-application-firewall-policy/tests/e2e/waf-aligned/main.test.bicep index 9fc72dff92..ecbe09e12c 100644 --- a/avm/res/network/front-door-web-application-firewall-policy/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/front-door-web-application-firewall-policy/tests/e2e/waf-aligned/main.test.bicep @@ -36,79 +36,81 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { // ============== // @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 - sku: 'Premium_AzureFrontDoor' - policySettings: { - mode: 'Prevention' - redirectUrl: 'http://www.bing.com' - customBlockResponseStatusCode: 200 - customBlockResponseBody: 'PGh0bWw+CjxoZWFkZXI+PHRpdGxlPkhlbGxvPC90aXRsZT48L2hlYWRlcj4KPGJvZHk+CkhlbGxvIHdvcmxkCjwvYm9keT4KPC9odG1sPg==' - } - customRules: { - rules: [ - { - name: 'CustomRule1' - priority: 2 - enabledState: 'Enabled' - action: 'Block' - ruleType: 'MatchRule' - rateLimitDurationInMinutes: 1 - rateLimitThreshold: 10 - matchConditions: [ - { - matchVariable: 'RemoteAddr' - selector: null - operator: 'GeoMatch' - negateCondition: false - transforms: [] - matchValue: [ - 'CH' - ] - } - { - matchVariable: 'RequestHeader' - selector: 'UserAgent' - operator: 'Contains' - negateCondition: false - transforms: [] - matchValue: [ - 'windows' - ] - } - { - matchVariable: 'QueryString' - operator: 'Contains' - negateCondition: false - transforms: [ - 'UrlDecode' - 'Lowercase' - ] - matchValue: [ - '' - ] - } - ] - } - ] - } - managedRules: { - managedRuleSets: [ - { - ruleSetType: 'Microsoft_BotManagerRuleSet' - ruleSetVersion: '1.0' - } - ] - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +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 + sku: 'Premium_AzureFrontDoor' + policySettings: { + mode: 'Prevention' + redirectUrl: 'http://www.bing.com' + customBlockResponseStatusCode: 200 + customBlockResponseBody: 'PGh0bWw+CjxoZWFkZXI+PHRpdGxlPkhlbGxvPC90aXRsZT48L2hlYWRlcj4KPGJvZHk+CkhlbGxvIHdvcmxkCjwvYm9keT4KPC9odG1sPg==' + } + customRules: { + rules: [ + { + name: 'CustomRule1' + priority: 2 + enabledState: 'Enabled' + action: 'Block' + ruleType: 'MatchRule' + rateLimitDurationInMinutes: 1 + rateLimitThreshold: 10 + matchConditions: [ + { + matchVariable: 'RemoteAddr' + selector: null + operator: 'GeoMatch' + negateCondition: false + transforms: [] + matchValue: [ + 'CH' + ] + } + { + matchVariable: 'RequestHeader' + selector: 'UserAgent' + operator: 'Contains' + negateCondition: false + transforms: [] + matchValue: [ + 'windows' + ] + } + { + matchVariable: 'QueryString' + operator: 'Contains' + negateCondition: false + transforms: [ + 'UrlDecode' + 'Lowercase' + ] + matchValue: [ + '' + ] + } + ] + } + ] + } + managedRules: { + managedRuleSets: [ + { + ruleSetType: 'Microsoft_BotManagerRuleSet' + ruleSetVersion: '1.0' + } + ] + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } } -}] +] diff --git a/avm/res/network/front-door/main.bicep b/avm/res/network/front-door/main.bicep index d121c34cb1..e8844b22a1 100644 --- a/avm/res/network/front-door/main.bicep +++ b/avm/res/network/front-door/main.bicep @@ -55,30 +55,40 @@ param diagnosticSettings diagnosticSettingType var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + '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') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-frontdoor.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-frontdoor.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource frontDoor 'Microsoft.Network/frontDoors@2020-05-01' = { name: name @@ -99,51 +109,66 @@ resource frontDoor 'Microsoft.Network/frontDoors@2020-05-01' = { } } -resource frontDoor_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.' +resource frontDoor_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: frontDoor } - scope: frontDoor -} -resource frontDoor_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource frontDoor_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: frontDoor } - scope: frontDoor -}] - -resource frontDoor_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(frontDoor.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +] + +resource frontDoor_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(frontDoor.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: frontDoor } - scope: frontDoor -}] +] @description('The name of the front door.') output name string = frontDoor.name diff --git a/avm/res/network/front-door/main.json b/avm/res/network/front-door/main.json index 140a73c6ad..067451e5f1 100644 --- a/avm/res/network/front-door/main.json +++ b/avm/res/network/front-door/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "5209569003361494357" + "version": "0.26.54.24096", + "templateHash": "11688367630078848691" }, "name": "Azure Front Doors", "description": "This module deploys an Azure Front Door.", diff --git a/avm/res/network/front-door/tests/e2e/defaults/main.test.bicep b/avm/res/network/front-door/tests/e2e/defaults/main.test.bicep index 9da362d16d..fc0f9d4bea 100644 --- a/avm/res/network/front-door/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/front-door/tests/e2e/defaults/main.test.bicep @@ -36,90 +36,92 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // var resourceName = '${namePrefix}${serviceShort}001' @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - name: resourceName - location: resourceLocation - frontendEndpoints: [ - { - name: 'frontEnd' - properties: { - hostName: '${resourceName}.${environment().suffixes.azureFrontDoorEndpointSuffix}' - sessionAffinityEnabledState: 'Disabled' - sessionAffinityTtlSeconds: 60 +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: resourceName + location: resourceLocation + frontendEndpoints: [ + { + name: 'frontEnd' + properties: { + hostName: '${resourceName}.${environment().suffixes.azureFrontDoorEndpointSuffix}' + sessionAffinityEnabledState: 'Disabled' + sessionAffinityTtlSeconds: 60 + } } - } - ] - healthProbeSettings: [ - { - name: 'heathProbe' - properties: { - intervalInSeconds: 60 - path: '/' - protocol: 'Https' + ] + healthProbeSettings: [ + { + name: 'heathProbe' + properties: { + intervalInSeconds: 60 + path: '/' + protocol: 'Https' + } } - } - ] - loadBalancingSettings: [ - { - name: 'loadBalancer' - properties: { - additionalLatencyMilliseconds: 0 - sampleSize: 50 - successfulSamplesRequired: 1 + ] + loadBalancingSettings: [ + { + name: 'loadBalancer' + properties: { + additionalLatencyMilliseconds: 0 + sampleSize: 50 + successfulSamplesRequired: 1 + } } - } - ] - routingRules: [ - { - name: 'routingRule' - properties: { - acceptedProtocols: [ - 'Https' - ] - enabledState: 'Enabled' - frontendEndpoints: [ - { - id: '${resourceGroup.id}/providers/Microsoft.Network/frontDoors/${resourceName}/FrontendEndpoints/frontEnd' - } - ] - patternsToMatch: [ - '/*' - ] - routeConfiguration: { - '@odata.type': '#Microsoft.Azure.FrontDoor.Models.FrontdoorForwardingConfiguration' - backendPool: { - id: '${resourceGroup.id}/providers/Microsoft.Network/frontDoors/${resourceName}/BackendPools/backendPool' + ] + routingRules: [ + { + name: 'routingRule' + properties: { + acceptedProtocols: [ + 'Https' + ] + enabledState: 'Enabled' + frontendEndpoints: [ + { + id: '${resourceGroup.id}/providers/Microsoft.Network/frontDoors/${resourceName}/FrontendEndpoints/frontEnd' + } + ] + patternsToMatch: [ + '/*' + ] + routeConfiguration: { + '@odata.type': '#Microsoft.Azure.FrontDoor.Models.FrontdoorForwardingConfiguration' + backendPool: { + id: '${resourceGroup.id}/providers/Microsoft.Network/frontDoors/${resourceName}/BackendPools/backendPool' + } } } } - } - ] - backendPools: [ - { - name: 'backendPool' - properties: { - backends: [ - { - address: 'biceptest.local' - backendHostHeader: 'backendAddress' - enabledState: 'Enabled' - httpPort: 80 - httpsPort: 443 - priority: 1 - weight: 50 + ] + backendPools: [ + { + name: 'backendPool' + properties: { + backends: [ + { + address: 'biceptest.local' + backendHostHeader: 'backendAddress' + enabledState: 'Enabled' + httpPort: 80 + httpsPort: 443 + priority: 1 + weight: 50 + } + ] + HealthProbeSettings: { + id: '${resourceGroup.id}/providers/Microsoft.Network/frontDoors/${resourceName}/HealthProbeSettings/heathProbe' + } + LoadBalancingSettings: { + id: '${resourceGroup.id}/providers/Microsoft.Network/frontDoors/${resourceName}/LoadBalancingSettings/loadBalancer' } - ] - HealthProbeSettings: { - id: '${resourceGroup.id}/providers/Microsoft.Network/frontDoors/${resourceName}/HealthProbeSettings/heathProbe' - } - LoadBalancingSettings: { - id: '${resourceGroup.id}/providers/Microsoft.Network/frontDoors/${resourceName}/LoadBalancingSettings/loadBalancer' } } - } - ] + ] + } } -}] +] diff --git a/avm/res/network/front-door/tests/e2e/max/dependencies.bicep b/avm/res/network/front-door/tests/e2e/max/dependencies.bicep index a7f42aee7b..7be39e253a 100644 --- a/avm/res/network/front-door/tests/e2e/max/dependencies.bicep +++ b/avm/res/network/front-door/tests/e2e/max/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/network/front-door/tests/e2e/max/main.test.bicep b/avm/res/network/front-door/tests/e2e/max/main.test.bicep index aa6d4a9abe..4207e72e65 100644 --- a/avm/res/network/front-door/tests/e2e/max/main.test.bicep +++ b/avm/res/network/front-door/tests/e2e/max/main.test.bicep @@ -59,144 +59,149 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t // ============== // var resourceName = '${namePrefix}${serviceShort}001' @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - name: resourceName - location: resourceLocation - backendPools: [ - { - name: 'backendPool' - properties: { - backends: [ - { - address: 'biceptest.local' - backendHostHeader: 'backendAddress' - enabledState: 'Enabled' - httpPort: 80 - httpsPort: 443 - priority: 1 - privateLinkAlias: '' - privateLinkApprovalMessage: '' - privateLinkLocation: '' - weight: 50 +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: resourceName + location: resourceLocation + backendPools: [ + { + name: 'backendPool' + properties: { + backends: [ + { + address: 'biceptest.local' + backendHostHeader: 'backendAddress' + enabledState: 'Enabled' + httpPort: 80 + httpsPort: 443 + priority: 1 + privateLinkAlias: '' + privateLinkApprovalMessage: '' + privateLinkLocation: '' + weight: 50 + } + ] + HealthProbeSettings: { + id: '${resourceGroup.id}/providers/Microsoft.Network/frontDoors/${resourceName}/HealthProbeSettings/heathProbe' + } + LoadBalancingSettings: { + id: '${resourceGroup.id}/providers/Microsoft.Network/frontDoors/${resourceName}/LoadBalancingSettings/loadBalancer' } - ] - HealthProbeSettings: { - id: '${resourceGroup.id}/providers/Microsoft.Network/frontDoors/${resourceName}/HealthProbeSettings/heathProbe' } - LoadBalancingSettings: { - id: '${resourceGroup.id}/providers/Microsoft.Network/frontDoors/${resourceName}/LoadBalancingSettings/loadBalancer' + } + ] + enforceCertificateNameCheck: 'Disabled' + frontendEndpoints: [ + { + name: 'frontEnd' + properties: { + hostName: '${resourceName}.${environment().suffixes.azureFrontDoorEndpointSuffix}' + sessionAffinityEnabledState: 'Disabled' + sessionAffinityTtlSeconds: 60 } } - } - ] - enforceCertificateNameCheck: 'Disabled' - frontendEndpoints: [ - { - name: 'frontEnd' - properties: { - hostName: '${resourceName}.${environment().suffixes.azureFrontDoorEndpointSuffix}' - sessionAffinityEnabledState: 'Disabled' - sessionAffinityTtlSeconds: 60 + ] + healthProbeSettings: [ + { + name: 'heathProbe' + properties: { + enabledState: '' + healthProbeMethod: '' + intervalInSeconds: 60 + path: '/' + protocol: 'Https' + } } - } - ] - healthProbeSettings: [ - { - name: 'heathProbe' - properties: { - enabledState: '' - healthProbeMethod: '' - intervalInSeconds: 60 - path: '/' - protocol: 'Https' + ] + loadBalancingSettings: [ + { + name: 'loadBalancer' + properties: { + additionalLatencyMilliseconds: 0 + sampleSize: 50 + successfulSamplesRequired: 1 + } } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - loadBalancingSettings: [ - { - name: 'loadBalancer' - properties: { - additionalLatencyMilliseconds: 0 - sampleSize: 50 - successfulSamplesRequired: 1 + routingRules: [ + { + name: 'routingRule' + properties: { + acceptedProtocols: [ + 'Http' + 'Https' + ] + enabledState: 'Enabled' + frontendEndpoints: [ + { + id: '${resourceGroup.id}/providers/Microsoft.Network/frontDoors/${resourceName}/FrontendEndpoints/frontEnd' + } + ] + patternsToMatch: [ + '/*' + ] + routeConfiguration: { + '@odata.type': '#Microsoft.Azure.FrontDoor.Models.FrontdoorForwardingConfiguration' + backendPool: { + id: '${resourceGroup.id}/providers/Microsoft.Network/frontDoors/${resourceName}/BackendPools/backendPool' + } + forwardingProtocol: 'MatchRequest' + } + } } - } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - routingRules: [ - { - name: 'routingRule' - properties: { - acceptedProtocols: [ - 'Http' - 'Https' - ] - enabledState: 'Enabled' - frontendEndpoints: [ + ] + sendRecvTimeoutSeconds: 10 + 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: [ { - id: '${resourceGroup.id}/providers/Microsoft.Network/frontDoors/${resourceName}/FrontendEndpoints/frontEnd' + category: 'AllMetrics' } ] - patternsToMatch: [ - '/*' - ] - routeConfiguration: { - '@odata.type': '#Microsoft.Azure.FrontDoor.Models.FrontdoorForwardingConfiguration' - backendPool: { - id: '${resourceGroup.id}/providers/Microsoft.Network/frontDoors/${resourceName}/BackendPools/backendPool' + logCategoriesAndGroups: [ + { + category: 'FrontdoorAccessLog' } - forwardingProtocol: 'MatchRequest' - } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - sendRecvTimeoutSeconds: 10 - 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' - } - ] - logCategoriesAndGroups: [ - { - category: 'FrontdoorAccessLog' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/network/front-door/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/front-door/tests/e2e/waf-aligned/main.test.bicep index 99c37e7c9b..fd7839f280 100644 --- a/avm/res/network/front-door/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/front-door/tests/e2e/waf-aligned/main.test.bicep @@ -50,112 +50,114 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t // ============== // var resourceName = '${namePrefix}${serviceShort}001' @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - name: resourceName - location: resourceLocation - backendPools: [ - { - name: 'backendPool' - properties: { - backends: [ - { - address: 'biceptest.local' - backendHostHeader: 'backendAddress' - enabledState: 'Enabled' - httpPort: 80 - httpsPort: 443 - priority: 1 - privateLinkAlias: '' - privateLinkApprovalMessage: '' - privateLinkLocation: '' - weight: 50 +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: resourceName + location: resourceLocation + backendPools: [ + { + name: 'backendPool' + properties: { + backends: [ + { + address: 'biceptest.local' + backendHostHeader: 'backendAddress' + enabledState: 'Enabled' + httpPort: 80 + httpsPort: 443 + priority: 1 + privateLinkAlias: '' + privateLinkApprovalMessage: '' + privateLinkLocation: '' + weight: 50 + } + ] + HealthProbeSettings: { + id: '${resourceGroup.id}/providers/Microsoft.Network/frontDoors/${resourceName}/HealthProbeSettings/heathProbe' + } + LoadBalancingSettings: { + id: '${resourceGroup.id}/providers/Microsoft.Network/frontDoors/${resourceName}/LoadBalancingSettings/loadBalancer' } - ] - HealthProbeSettings: { - id: '${resourceGroup.id}/providers/Microsoft.Network/frontDoors/${resourceName}/HealthProbeSettings/heathProbe' - } - LoadBalancingSettings: { - id: '${resourceGroup.id}/providers/Microsoft.Network/frontDoors/${resourceName}/LoadBalancingSettings/loadBalancer' } } - } - ] - enforceCertificateNameCheck: 'Disabled' - frontendEndpoints: [ - { - name: 'frontEnd' - properties: { - hostName: '${resourceName}.${environment().suffixes.azureFrontDoorEndpointSuffix}' - sessionAffinityEnabledState: 'Disabled' - sessionAffinityTtlSeconds: 60 + ] + enforceCertificateNameCheck: 'Disabled' + frontendEndpoints: [ + { + name: 'frontEnd' + properties: { + hostName: '${resourceName}.${environment().suffixes.azureFrontDoorEndpointSuffix}' + sessionAffinityEnabledState: 'Disabled' + sessionAffinityTtlSeconds: 60 + } } - } - ] - healthProbeSettings: [ - { - name: 'heathProbe' - properties: { - enabledState: '' - healthProbeMethod: '' - intervalInSeconds: 60 - path: '/' - protocol: 'Https' + ] + healthProbeSettings: [ + { + name: 'heathProbe' + properties: { + enabledState: '' + healthProbeMethod: '' + intervalInSeconds: 60 + path: '/' + protocol: 'Https' + } } - } - ] - loadBalancingSettings: [ - { - name: 'loadBalancer' - properties: { - additionalLatencyMilliseconds: 0 - sampleSize: 50 - successfulSamplesRequired: 1 + ] + loadBalancingSettings: [ + { + name: 'loadBalancer' + properties: { + additionalLatencyMilliseconds: 0 + sampleSize: 50 + successfulSamplesRequired: 1 + } } - } - ] - routingRules: [ - { - name: 'routingRule' - properties: { - acceptedProtocols: [ - 'Http' - 'Https' - ] - enabledState: 'Enabled' - frontendEndpoints: [ - { - id: '${resourceGroup.id}/providers/Microsoft.Network/frontDoors/${resourceName}/FrontendEndpoints/frontEnd' + ] + routingRules: [ + { + name: 'routingRule' + properties: { + acceptedProtocols: [ + 'Http' + 'Https' + ] + enabledState: 'Enabled' + frontendEndpoints: [ + { + id: '${resourceGroup.id}/providers/Microsoft.Network/frontDoors/${resourceName}/FrontendEndpoints/frontEnd' + } + ] + patternsToMatch: [ + '/*' + ] + routeConfiguration: { + '@odata.type': '#Microsoft.Azure.FrontDoor.Models.FrontdoorForwardingConfiguration' + backendPool: { + id: '${resourceGroup.id}/providers/Microsoft.Network/frontDoors/${resourceName}/BackendPools/backendPool' + } + forwardingProtocol: 'MatchRequest' } - ] - patternsToMatch: [ - '/*' - ] - routeConfiguration: { - '@odata.type': '#Microsoft.Azure.FrontDoor.Models.FrontdoorForwardingConfiguration' - backendPool: { - id: '${resourceGroup.id}/providers/Microsoft.Network/frontDoors/${resourceName}/BackendPools/backendPool' - } - forwardingProtocol: 'MatchRequest' } } + ] + sendRecvTimeoutSeconds: 10 + diagnosticSettings: [ + { + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - sendRecvTimeoutSeconds: 10 - diagnosticSettings: [ - { - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/network/ip-group/main.bicep b/avm/res/network/ip-group/main.bicep index 9232554ce1..0363fa601c 100644 --- a/avm/res/network/ip-group/main.bicep +++ b/avm/res/network/ip-group/main.bicep @@ -26,30 +26,40 @@ param enableTelemetry bool = true var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'IPAM Pool Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b3e853f-ad5d-4fb5-a7b8-56a3581c7037') - 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'IPAM Pool Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '7b3e853f-ad5d-4fb5-a7b8-56a3581c7037' + ) + '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') + 'Role Based Access Control Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-ipgroup.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-ipgroup.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource ipGroup 'Microsoft.Network/ipGroups@2023-04-01' = { name: name @@ -60,28 +70,37 @@ resource ipGroup 'Microsoft.Network/ipGroups@2023-04-01' = { } } -resource ipGroup_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.' +resource ipGroup_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: ipGroup } - scope: ipGroup -} -resource ipGroup_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(ipGroup.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource ipGroup_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(ipGroup.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: ipGroup } - scope: ipGroup -}] +] @description('The resource ID of the IP group.') output resourceId string = ipGroup.id diff --git a/avm/res/network/ip-group/main.json b/avm/res/network/ip-group/main.json index c190237042..733445b2c1 100644 --- a/avm/res/network/ip-group/main.json +++ b/avm/res/network/ip-group/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3252011302585807507" + "version": "0.26.54.24096", + "templateHash": "6270017838054314226" }, "name": "IP Groups", "description": "This module deploys an IP Group.", diff --git a/avm/res/network/ip-group/tests/e2e/defaults/main.test.bicep b/avm/res/network/ip-group/tests/e2e/defaults/main.test.bicep index 6341b22f1e..fd0de68ed1 100644 --- a/avm/res/network/ip-group/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/ip-group/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 +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 + } } -}] +] diff --git a/avm/res/network/ip-group/tests/e2e/max/dependencies.bicep b/avm/res/network/ip-group/tests/e2e/max/dependencies.bicep index a7f42aee7b..7be39e253a 100644 --- a/avm/res/network/ip-group/tests/e2e/max/dependencies.bicep +++ b/avm/res/network/ip-group/tests/e2e/max/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/network/ip-group/tests/e2e/max/main.test.bicep b/avm/res/network/ip-group/tests/e2e/max/main.test.bicep index 7e5f42408f..7b64b4b2be 100644 --- a/avm/res/network/ip-group/tests/e2e/max/main.test.bicep +++ b/avm/res/network/ip-group/tests/e2e/max/main.test.bicep @@ -45,41 +45,46 @@ 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 - ipAddresses: [ - '10.0.0.1' - '10.0.0.2' - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +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 + ipAddresses: [ + '10.0.0.1' + '10.0.0.2' + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/network/ip-group/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/ip-group/tests/e2e/waf-aligned/main.test.bicep index 9c0a4a3e10..35516eff9a 100644 --- a/avm/res/network/ip-group/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/ip-group/tests/e2e/waf-aligned/main.test.bicep @@ -36,20 +36,22 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 - ipAddresses: [ - '10.0.0.1' - '10.0.0.2' - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +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 + ipAddresses: [ + '10.0.0.1' + '10.0.0.2' + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } } -}] +] diff --git a/avm/res/network/load-balancer/backend-address-pool/main.json b/avm/res/network/load-balancer/backend-address-pool/main.json index ab6d005e2d..f54d506c5f 100644 --- a/avm/res/network/load-balancer/backend-address-pool/main.json +++ b/avm/res/network/load-balancer/backend-address-pool/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16244632442901566911" + "version": "0.26.54.24096", + "templateHash": "17412878196552582226" }, "name": "Load Balancer Backend Address Pools", "description": "This module deploys a Load Balancer Backend Address Pools.", diff --git a/avm/res/network/load-balancer/inbound-nat-rule/main.bicep b/avm/res/network/load-balancer/inbound-nat-rule/main.bicep index cd2a670107..de3cfa7775 100644 --- a/avm/res/network/load-balancer/inbound-nat-rule/main.bicep +++ b/avm/res/network/load-balancer/inbound-nat-rule/main.bicep @@ -60,9 +60,11 @@ resource inboundNatRule 'Microsoft.Network/loadBalancers/inboundNatRules@2023-04 properties: { frontendPort: frontendPort backendPort: backendPort - backendAddressPool: !empty(backendAddressPoolName) ? { - id: '${loadBalancer.id}/backendAddressPools/${backendAddressPoolName}' - } : null + backendAddressPool: !empty(backendAddressPoolName) + ? { + id: '${loadBalancer.id}/backendAddressPools/${backendAddressPoolName}' + } + : null enableFloatingIP: enableFloatingIP enableTcpReset: enableTcpReset frontendIPConfiguration: { diff --git a/avm/res/network/load-balancer/inbound-nat-rule/main.json b/avm/res/network/load-balancer/inbound-nat-rule/main.json index 08de35dd26..23878519ea 100644 --- a/avm/res/network/load-balancer/inbound-nat-rule/main.json +++ b/avm/res/network/load-balancer/inbound-nat-rule/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17788406033422026149" + "version": "0.26.54.24096", + "templateHash": "7362889285586557037" }, "name": "Load Balancer Inbound NAT Rules", "description": "This module deploys a Load Balancer Inbound NAT Rules.", diff --git a/avm/res/network/load-balancer/main.bicep b/avm/res/network/load-balancer/main.bicep index 081b5c1b8a..1e956dae91 100644 --- a/avm/res/network/load-balancer/main.bicep +++ b/avm/res/network/load-balancer/main.bicep @@ -57,113 +57,169 @@ param outboundRules array = [] // Variables // // =========== // -var frontendIPConfigurationsVar = [for (frontendIPConfiguration, index) in frontendIPConfigurations: { - name: frontendIPConfiguration.name - properties: { - subnet: contains(frontendIPConfiguration, 'subnetId') && !empty(frontendIPConfiguration.subnetId) ? { - id: frontendIPConfiguration.subnetId - } : null - publicIPAddress: contains(frontendIPConfiguration, 'publicIPAddressId') && !empty(frontendIPConfiguration.publicIPAddressId) ? { - id: frontendIPConfiguration.publicIPAddressId - } : null - privateIPAddress: contains(frontendIPConfiguration, 'privateIPAddress') && !empty(frontendIPConfiguration.privateIPAddress) ? frontendIPConfiguration.privateIPAddress : null - privateIPAddressVersion: contains(frontendIPConfiguration, 'privateIPAddressVersion') ? frontendIPConfiguration.privateIPAddressVersion : 'IPv4' - privateIPAllocationMethod: contains(frontendIPConfiguration, 'subnetId') && !empty(frontendIPConfiguration.subnetId) ? (contains(frontendIPConfiguration, 'privateIPAddress') ? 'Static' : 'Dynamic') : null - gatewayLoadBalancer: contains(frontendIPConfiguration, 'gatewayLoadBalancer') && !empty(frontendIPConfiguration.gatewayLoadBalancer) ? { - id: frontendIPConfiguration.gatewayLoadBalancer - } : null - publicIPPrefix: contains(frontendIPConfiguration, 'publicIPPrefix') && !empty(frontendIPConfiguration.publicIPPrefix) ? { - id: frontendIPConfiguration.publicIPPrefix - } : null - } -}] - -var loadBalancingRulesVar = [for loadBalancingRule in (loadBalancingRules ?? []): { - name: loadBalancingRule.name - properties: { - backendAddressPool: { - id: az.resourceId('Microsoft.Network/loadBalancers/backendAddressPools', name, loadBalancingRule.backendAddressPoolName) - } - backendPort: loadBalancingRule.backendPort - disableOutboundSnat: contains(loadBalancingRule, 'disableOutboundSnat') ? loadBalancingRule.disableOutboundSnat : true - enableFloatingIP: contains(loadBalancingRule, 'enableFloatingIP') ? loadBalancingRule.enableFloatingIP : false - enableTcpReset: contains(loadBalancingRule, 'enableTcpReset') ? loadBalancingRule.enableTcpReset : false - frontendIPConfiguration: { - id: az.resourceId('Microsoft.Network/loadBalancers/frontendIPConfigurations', name, loadBalancingRule.frontendIPConfigurationName) +var frontendIPConfigurationsVar = [ + for (frontendIPConfiguration, index) in frontendIPConfigurations: { + name: frontendIPConfiguration.name + properties: { + subnet: contains(frontendIPConfiguration, 'subnetId') && !empty(frontendIPConfiguration.subnetId) + ? { + id: frontendIPConfiguration.subnetId + } + : null + publicIPAddress: contains(frontendIPConfiguration, 'publicIPAddressId') && !empty(frontendIPConfiguration.publicIPAddressId) + ? { + id: frontendIPConfiguration.publicIPAddressId + } + : null + privateIPAddress: contains(frontendIPConfiguration, 'privateIPAddress') && !empty(frontendIPConfiguration.privateIPAddress) + ? frontendIPConfiguration.privateIPAddress + : null + privateIPAddressVersion: contains(frontendIPConfiguration, 'privateIPAddressVersion') + ? frontendIPConfiguration.privateIPAddressVersion + : 'IPv4' + privateIPAllocationMethod: contains(frontendIPConfiguration, 'subnetId') && !empty(frontendIPConfiguration.subnetId) + ? (contains(frontendIPConfiguration, 'privateIPAddress') ? 'Static' : 'Dynamic') + : null + gatewayLoadBalancer: contains(frontendIPConfiguration, 'gatewayLoadBalancer') && !empty(frontendIPConfiguration.gatewayLoadBalancer) + ? { + id: frontendIPConfiguration.gatewayLoadBalancer + } + : null + publicIPPrefix: contains(frontendIPConfiguration, 'publicIPPrefix') && !empty(frontendIPConfiguration.publicIPPrefix) + ? { + id: frontendIPConfiguration.publicIPPrefix + } + : null } - frontendPort: loadBalancingRule.frontendPort - idleTimeoutInMinutes: contains(loadBalancingRule, 'idleTimeoutInMinutes') ? loadBalancingRule.idleTimeoutInMinutes : 4 - loadDistribution: contains(loadBalancingRule, 'loadDistribution') ? loadBalancingRule.loadDistribution : 'Default' - probe: { - id: '${az.resourceId('Microsoft.Network/loadBalancers', name)}/probes/${loadBalancingRule.probeName}' + } +] + +var loadBalancingRulesVar = [ + for loadBalancingRule in (loadBalancingRules ?? []): { + name: loadBalancingRule.name + properties: { + backendAddressPool: { + id: az.resourceId( + 'Microsoft.Network/loadBalancers/backendAddressPools', + name, + loadBalancingRule.backendAddressPoolName + ) + } + backendPort: loadBalancingRule.backendPort + disableOutboundSnat: contains(loadBalancingRule, 'disableOutboundSnat') + ? loadBalancingRule.disableOutboundSnat + : true + enableFloatingIP: contains(loadBalancingRule, 'enableFloatingIP') ? loadBalancingRule.enableFloatingIP : false + enableTcpReset: contains(loadBalancingRule, 'enableTcpReset') ? loadBalancingRule.enableTcpReset : false + frontendIPConfiguration: { + id: az.resourceId( + 'Microsoft.Network/loadBalancers/frontendIPConfigurations', + name, + loadBalancingRule.frontendIPConfigurationName + ) + } + frontendPort: loadBalancingRule.frontendPort + idleTimeoutInMinutes: contains(loadBalancingRule, 'idleTimeoutInMinutes') + ? loadBalancingRule.idleTimeoutInMinutes + : 4 + loadDistribution: contains(loadBalancingRule, 'loadDistribution') ? loadBalancingRule.loadDistribution : 'Default' + probe: { + id: '${az.resourceId('Microsoft.Network/loadBalancers', name)}/probes/${loadBalancingRule.probeName}' + } + protocol: contains(loadBalancingRule, 'protocol') ? loadBalancingRule.protocol : 'Tcp' } - protocol: contains(loadBalancingRule, 'protocol') ? loadBalancingRule.protocol : 'Tcp' } -}] - -var outboundRulesVar = [for outboundRule in outboundRules: { - name: outboundRule.name - properties: { - frontendIPConfigurations: [ - { - id: az.resourceId('Microsoft.Network/loadBalancers/frontendIPConfigurations', name, outboundRule.frontendIPConfigurationName) +] + +var outboundRulesVar = [ + for outboundRule in outboundRules: { + name: outboundRule.name + properties: { + frontendIPConfigurations: [ + { + id: az.resourceId( + 'Microsoft.Network/loadBalancers/frontendIPConfigurations', + name, + outboundRule.frontendIPConfigurationName + ) + } + ] + backendAddressPool: { + id: az.resourceId( + 'Microsoft.Network/loadBalancers/backendAddressPools', + name, + outboundRule.backendAddressPoolName + ) } - ] - backendAddressPool: { - id: az.resourceId('Microsoft.Network/loadBalancers/backendAddressPools', name, outboundRule.backendAddressPoolName) + protocol: contains(outboundRule, 'protocol') ? outboundRule.protocol : 'All' + allocatedOutboundPorts: contains(outboundRule, 'allocatedOutboundPorts') + ? outboundRule.allocatedOutboundPorts + : 63984 + enableTcpReset: contains(outboundRule, 'enableTcpReset') ? outboundRule.enableTcpReset : true + idleTimeoutInMinutes: contains(outboundRule, 'idleTimeoutInMinutes') ? outboundRule.idleTimeoutInMinutes : 4 } - protocol: contains(outboundRule, 'protocol') ? outboundRule.protocol : 'All' - allocatedOutboundPorts: contains(outboundRule, 'allocatedOutboundPorts') ? outboundRule.allocatedOutboundPorts : 63984 - enableTcpReset: contains(outboundRule, 'enableTcpReset') ? outboundRule.enableTcpReset : true - idleTimeoutInMinutes: contains(outboundRule, 'idleTimeoutInMinutes') ? outboundRule.idleTimeoutInMinutes : 4 } -}] - -var probesVar = [for probe in (probes ?? []): { - name: probe.name - properties: { - protocol: contains(probe, 'protocol') ? probe.protocol : 'Tcp' - requestPath: toLower(probe.protocol) != 'tcp' ? probe.requestPath : null - port: contains(probe, 'port') ? probe.port : 80 - intervalInSeconds: contains(probe, 'intervalInSeconds') ? probe.intervalInSeconds : 5 - numberOfProbes: contains(probe, 'numberOfProbes') ? probe.numberOfProbes : 2 +] + +var probesVar = [ + for probe in (probes ?? []): { + name: probe.name + properties: { + protocol: contains(probe, 'protocol') ? probe.protocol : 'Tcp' + requestPath: toLower(probe.protocol) != 'tcp' ? probe.requestPath : null + port: contains(probe, 'port') ? probe.port : 80 + intervalInSeconds: contains(probe, 'intervalInSeconds') ? probe.intervalInSeconds : 5 + numberOfProbes: contains(probe, 'numberOfProbes') ? probe.numberOfProbes : 2 + } } -}] +] -var backendAddressPoolNames = [for backendAddressPool in (backendAddressPools ?? []): { - name: backendAddressPool.name -}] +var backendAddressPoolNames = [ + for backendAddressPool in (backendAddressPools ?? []): { + name: backendAddressPool.name + } +] var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + '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') + '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' + ) } // ============ // // Dependencies // // ============ // -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-loadbalancer.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-loadbalancer.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource loadBalancer 'Microsoft.Network/loadBalancers@2023-04-01' = { name: name @@ -181,78 +237,105 @@ resource loadBalancer 'Microsoft.Network/loadBalancers@2023-04-01' = { } } -module loadBalancer_backendAddressPools 'backend-address-pool/main.bicep' = [for (backendAddressPool, index) in backendAddressPools ?? []: { - name: '${uniqueString(deployment().name, location)}-loadBalancer-backendAddressPools-${index}' - params: { - loadBalancerName: loadBalancer.name - name: backendAddressPool.name - tunnelInterfaces: contains(backendAddressPool, 'tunnelInterfaces') && !empty(backendAddressPool.tunnelInterfaces) ? backendAddressPool.tunnelInterfaces : [] - loadBalancerBackendAddresses: contains(backendAddressPool, 'loadBalancerBackendAddresses') && !empty(backendAddressPool.loadBalancerBackendAddresses) ? backendAddressPool.loadBalancerBackendAddresses : [] - drainPeriodInSeconds: contains(backendAddressPool, 'drainPeriodInSeconds') ? backendAddressPool.drainPeriodInSeconds : 0 +module loadBalancer_backendAddressPools 'backend-address-pool/main.bicep' = [ + for (backendAddressPool, index) in backendAddressPools ?? []: { + name: '${uniqueString(deployment().name, location)}-loadBalancer-backendAddressPools-${index}' + params: { + loadBalancerName: loadBalancer.name + name: backendAddressPool.name + tunnelInterfaces: contains(backendAddressPool, 'tunnelInterfaces') && !empty(backendAddressPool.tunnelInterfaces) + ? backendAddressPool.tunnelInterfaces + : [] + loadBalancerBackendAddresses: contains(backendAddressPool, 'loadBalancerBackendAddresses') && !empty(backendAddressPool.loadBalancerBackendAddresses) + ? backendAddressPool.loadBalancerBackendAddresses + : [] + drainPeriodInSeconds: contains(backendAddressPool, 'drainPeriodInSeconds') + ? backendAddressPool.drainPeriodInSeconds + : 0 + } } -}] - -module loadBalancer_inboundNATRules 'inbound-nat-rule/main.bicep' = [for (inboundNATRule, index) in inboundNatRules: { - name: '${uniqueString(deployment().name, location)}-LoadBalancer-inboundNatRules-${index}' - params: { - loadBalancerName: loadBalancer.name - name: inboundNATRule.name - frontendIPConfigurationName: inboundNATRule.frontendIPConfigurationName - frontendPort: inboundNATRule.frontendPort - backendPort: contains(inboundNATRule, 'backendPort') ? inboundNATRule.backendPort : inboundNATRule.frontendPort - backendAddressPoolName: contains(inboundNATRule, 'backendAddressPoolName') ? inboundNATRule.backendAddressPoolName : '' - enableFloatingIP: contains(inboundNATRule, 'enableFloatingIP') ? inboundNATRule.enableFloatingIP : false - enableTcpReset: contains(inboundNATRule, 'enableTcpReset') ? inboundNATRule.enableTcpReset : false - frontendPortRangeEnd: contains(inboundNATRule, 'frontendPortRangeEnd') ? inboundNATRule.frontendPortRangeEnd : -1 - frontendPortRangeStart: contains(inboundNATRule, 'frontendPortRangeStart') ? inboundNATRule.frontendPortRangeStart : -1 - idleTimeoutInMinutes: contains(inboundNATRule, 'idleTimeoutInMinutes') ? inboundNATRule.idleTimeoutInMinutes : 4 - protocol: contains(inboundNATRule, 'protocol') ? inboundNATRule.protocol : 'Tcp' +] + +module loadBalancer_inboundNATRules 'inbound-nat-rule/main.bicep' = [ + for (inboundNATRule, index) in inboundNatRules: { + name: '${uniqueString(deployment().name, location)}-LoadBalancer-inboundNatRules-${index}' + params: { + loadBalancerName: loadBalancer.name + name: inboundNATRule.name + frontendIPConfigurationName: inboundNATRule.frontendIPConfigurationName + frontendPort: inboundNATRule.frontendPort + backendPort: contains(inboundNATRule, 'backendPort') ? inboundNATRule.backendPort : inboundNATRule.frontendPort + backendAddressPoolName: contains(inboundNATRule, 'backendAddressPoolName') + ? inboundNATRule.backendAddressPoolName + : '' + enableFloatingIP: contains(inboundNATRule, 'enableFloatingIP') ? inboundNATRule.enableFloatingIP : false + enableTcpReset: contains(inboundNATRule, 'enableTcpReset') ? inboundNATRule.enableTcpReset : false + frontendPortRangeEnd: contains(inboundNATRule, 'frontendPortRangeEnd') ? inboundNATRule.frontendPortRangeEnd : -1 + frontendPortRangeStart: contains(inboundNATRule, 'frontendPortRangeStart') + ? inboundNATRule.frontendPortRangeStart + : -1 + idleTimeoutInMinutes: contains(inboundNATRule, 'idleTimeoutInMinutes') ? inboundNATRule.idleTimeoutInMinutes : 4 + protocol: contains(inboundNATRule, 'protocol') ? inboundNATRule.protocol : 'Tcp' + } + dependsOn: [ + loadBalancer_backendAddressPools + ] } - dependsOn: [ - loadBalancer_backendAddressPools - ] -}] - -resource loadBalancer_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.' +] + +resource loadBalancer_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: loadBalancer } - scope: loadBalancer -} -resource loadBalancer_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource loadBalancer_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: loadBalancer } - scope: loadBalancer -}] - -resource loadBalancer_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(loadBalancer.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +] + +resource loadBalancer_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(loadBalancer.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: loadBalancer } - scope: loadBalancer -}] +] // =========== // // Outputs // diff --git a/avm/res/network/load-balancer/main.json b/avm/res/network/load-balancer/main.json index 0596ec342f..9b5968693a 100644 --- a/avm/res/network/load-balancer/main.json +++ b/avm/res/network/load-balancer/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "5849926741790594100" + "version": "0.26.54.24096", + "templateHash": "13683964905263959387" }, "name": "Load Balancers", "description": "This module deploys a Load Balancer.", @@ -524,8 +524,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16244632442901566911" + "version": "0.26.54.24096", + "templateHash": "17412878196552582226" }, "name": "Load Balancer Backend Address Pools", "description": "This module deploys a Load Balancer Backend Address Pools.", @@ -661,8 +661,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17788406033422026149" + "version": "0.26.54.24096", + "templateHash": "7362889285586557037" }, "name": "Load Balancer Inbound NAT Rules", "description": "This module deploys a Load Balancer Inbound NAT Rules.", diff --git a/avm/res/network/load-balancer/tests/e2e/defaults/main.test.bicep b/avm/res/network/load-balancer/tests/e2e/defaults/main.test.bicep index 54b6794296..d2253a49c4 100644 --- a/avm/res/network/load-balancer/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/load-balancer/tests/e2e/defaults/main.test.bicep @@ -59,23 +59,25 @@ 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 - lock: {} - diagnosticSettings: [] - frontendIPConfigurations: [ - { - name: 'publicIPConfig1' - publicIPAddressId: nestedDependencies.outputs.publicIPResourceId - } +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 + lock: {} + diagnosticSettings: [] + frontendIPConfigurations: [ + { + name: 'publicIPConfig1' + publicIPAddressId: nestedDependencies.outputs.publicIPResourceId + } + ] + } + dependsOn: [ + nestedDependencies + diagnosticDependencies ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/network/load-balancer/tests/e2e/internal/main.test.bicep b/avm/res/network/load-balancer/tests/e2e/internal/main.test.bicep index e746a9b672..f0cc0f5f15 100644 --- a/avm/res/network/load-balancer/tests/e2e/internal/main.test.bicep +++ b/avm/res/network/load-balancer/tests/e2e/internal/main.test.bicep @@ -46,91 +46,96 @@ 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 - frontendIPConfigurations: [ - { - name: 'privateIPConfig1' - subnetId: nestedDependencies.outputs.subnetResourceId - } - ] - backendAddressPools: [ - { - name: 'servers' - } - ] - inboundNatRules: [ - { - backendPort: 443 - enableFloatingIP: false - enableTcpReset: false - frontendIPConfigurationName: 'privateIPConfig1' - frontendPort: 443 - idleTimeoutInMinutes: 4 - name: 'inboundNatRule1' - protocol: 'Tcp' - } - { - backendPort: 3389 - frontendIPConfigurationName: 'privateIPConfig1' - frontendPort: 3389 - name: 'inboundNatRule2' - } - ] - skuName: 'Standard' - loadBalancingRules: [ - { - backendAddressPoolName: 'servers' - backendPort: 0 - disableOutboundSnat: true - enableFloatingIP: true - enableTcpReset: false - frontendIPConfigurationName: 'privateIPConfig1' - frontendPort: 0 - idleTimeoutInMinutes: 4 - loadDistribution: 'Default' - name: 'privateIPLBRule1' - probeName: 'probe1' - protocol: 'All' - } - ] - probes: [ - { - intervalInSeconds: 5 - name: 'probe1' - numberOfProbes: 2 - port: '62000' - protocol: 'Tcp' - } - ] - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +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 + frontendIPConfigurations: [ + { + name: 'privateIPConfig1' + subnetId: nestedDependencies.outputs.subnetResourceId + } + ] + backendAddressPools: [ + { + name: 'servers' + } + ] + inboundNatRules: [ + { + backendPort: 443 + enableFloatingIP: false + enableTcpReset: false + frontendIPConfigurationName: 'privateIPConfig1' + frontendPort: 443 + idleTimeoutInMinutes: 4 + name: 'inboundNatRule1' + protocol: 'Tcp' + } + { + backendPort: 3389 + frontendIPConfigurationName: 'privateIPConfig1' + frontendPort: 3389 + name: 'inboundNatRule2' + } + ] + skuName: 'Standard' + loadBalancingRules: [ + { + backendAddressPoolName: 'servers' + backendPort: 0 + disableOutboundSnat: true + enableFloatingIP: true + enableTcpReset: false + frontendIPConfigurationName: 'privateIPConfig1' + frontendPort: 0 + idleTimeoutInMinutes: 4 + loadDistribution: 'Default' + name: 'privateIPLBRule1' + probeName: 'probe1' + protocol: 'All' + } + ] + probes: [ + { + intervalInSeconds: 5 + name: 'probe1' + numberOfProbes: 2 + port: '62000' + protocol: 'Tcp' + } + ] + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - { - 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' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/network/load-balancer/tests/e2e/max/main.test.bicep b/avm/res/network/load-balancer/tests/e2e/max/main.test.bicep index f65e294ea5..3090e1fd47 100644 --- a/avm/res/network/load-balancer/tests/e2e/max/main.test.bicep +++ b/avm/res/network/load-balancer/tests/e2e/max/main.test.bicep @@ -60,135 +60,140 @@ 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 - frontendIPConfigurations: [ - { - name: 'publicIPConfig1' - publicIPAddressId: nestedDependencies.outputs.publicIPResourceId - } - ] - backendAddressPools: [ - { - name: 'backendAddressPool1' - } - { - name: 'backendAddressPool2' +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 + frontendIPConfigurations: [ + { + name: 'publicIPConfig1' + publicIPAddressId: nestedDependencies.outputs.publicIPResourceId + } + ] + backendAddressPools: [ + { + name: 'backendAddressPool1' + } + { + name: 'backendAddressPool2' + } + ] + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + inboundNatRules: [ + { + backendPort: 443 + enableFloatingIP: false + enableTcpReset: false + frontendIPConfigurationName: 'publicIPConfig1' + frontendPort: 443 + idleTimeoutInMinutes: 4 + name: 'inboundNatRule1' + protocol: 'Tcp' + } + { + backendPort: 3389 + frontendIPConfigurationName: 'publicIPConfig1' + frontendPort: 3389 + name: 'inboundNatRule2' + } + ] + loadBalancingRules: [ + { + backendAddressPoolName: 'backendAddressPool1' + backendPort: 80 + disableOutboundSnat: true + enableFloatingIP: false + enableTcpReset: false + frontendIPConfigurationName: 'publicIPConfig1' + frontendPort: 80 + idleTimeoutInMinutes: 5 + loadDistribution: 'Default' + name: 'publicIPLBRule1' + probeName: 'probe1' + protocol: 'Tcp' + } + { + backendAddressPoolName: 'backendAddressPool2' + backendPort: 8080 + frontendIPConfigurationName: 'publicIPConfig1' + frontendPort: 8080 + loadDistribution: 'Default' + name: 'publicIPLBRule2' + probeName: 'probe2' + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - inboundNatRules: [ - { - backendPort: 443 - enableFloatingIP: false - enableTcpReset: false - frontendIPConfigurationName: 'publicIPConfig1' - frontendPort: 443 - idleTimeoutInMinutes: 4 - name: 'inboundNatRule1' - protocol: 'Tcp' - } - { - backendPort: 3389 - frontendIPConfigurationName: 'publicIPConfig1' - frontendPort: 3389 - name: 'inboundNatRule2' - } - ] - loadBalancingRules: [ - { - backendAddressPoolName: 'backendAddressPool1' - backendPort: 80 - disableOutboundSnat: true - enableFloatingIP: false - enableTcpReset: false - frontendIPConfigurationName: 'publicIPConfig1' - frontendPort: 80 - idleTimeoutInMinutes: 5 - loadDistribution: 'Default' - name: 'publicIPLBRule1' - probeName: 'probe1' - protocol: 'Tcp' + outboundRules: [ + { + allocatedOutboundPorts: 63984 + backendAddressPoolName: 'backendAddressPool1' + frontendIPConfigurationName: 'publicIPConfig1' + name: 'outboundRule1' + } + ] + probes: [ + { + intervalInSeconds: 10 + name: 'probe1' + numberOfProbes: 5 + port: 80 + protocol: 'Tcp' + } + { + name: 'probe2' + port: 443 + protocol: 'Https' + requestPath: '/' + } + ] + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - { - backendAddressPoolName: 'backendAddressPool2' - backendPort: 8080 - frontendIPConfigurationName: 'publicIPConfig1' - frontendPort: 8080 - loadDistribution: 'Default' - name: 'publicIPLBRule2' - probeName: 'probe2' - } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' } - outboundRules: [ - { - allocatedOutboundPorts: 63984 - backendAddressPoolName: 'backendAddressPool1' - frontendIPConfigurationName: 'publicIPConfig1' - name: 'outboundRule1' - } - ] - probes: [ - { - intervalInSeconds: 10 - name: 'probe1' - numberOfProbes: 5 - port: 80 - protocol: 'Tcp' - } - { - name: 'probe2' - port: 443 - protocol: 'Https' - requestPath: '/' - } + dependsOn: [ + nestedDependencies + diagnosticDependencies ] - 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' - } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/network/load-balancer/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/load-balancer/tests/e2e/waf-aligned/main.test.bicep index 3392d94b44..de132072e4 100644 --- a/avm/res/network/load-balancer/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/load-balancer/tests/e2e/waf-aligned/main.test.bicep @@ -60,136 +60,141 @@ 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 - frontendIPConfigurations: [ - { - name: 'publicIPConfig1' - publicIPAddressId: nestedDependencies.outputs.publicIPResourceId - } - ] - backendAddressPools: [ - { - name: 'backendAddressPool1' - } - { - name: 'backendAddressPool2' +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 + frontendIPConfigurations: [ + { + name: 'publicIPConfig1' + publicIPAddressId: nestedDependencies.outputs.publicIPResourceId + } + ] + backendAddressPools: [ + { + name: 'backendAddressPool1' + } + { + name: 'backendAddressPool2' + } + ] + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + inboundNatRules: [ + { + backendPort: 443 + enableFloatingIP: false + enableTcpReset: false + frontendIPConfigurationName: 'publicIPConfig1' + frontendPort: 443 + idleTimeoutInMinutes: 4 + name: 'inboundNatRule1' + protocol: 'Tcp' + } + { + backendPort: 3389 + frontendIPConfigurationName: 'publicIPConfig1' + frontendPort: 3389 + name: 'inboundNatRule2' + } + ] + loadBalancingRules: [ + { + backendAddressPoolName: 'backendAddressPool1' + backendPort: 80 + disableOutboundSnat: true + enableFloatingIP: false + enableTcpReset: false + frontendIPConfigurationName: 'publicIPConfig1' + frontendPort: 80 + idleTimeoutInMinutes: 5 + loadDistribution: 'Default' + name: 'publicIPLBRule1' + probeName: 'probe1' + protocol: 'Tcp' + } + { + backendAddressPoolName: 'backendAddressPool2' + backendPort: 8080 + frontendIPConfigurationName: 'publicIPConfig1' + frontendPort: 8080 + loadDistribution: 'Default' + name: 'publicIPLBRule2' + probeName: 'probe2' + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - inboundNatRules: [ - { - backendPort: 443 - enableFloatingIP: false - enableTcpReset: false - frontendIPConfigurationName: 'publicIPConfig1' - frontendPort: 443 - idleTimeoutInMinutes: 4 - name: 'inboundNatRule1' - protocol: 'Tcp' - } - { - backendPort: 3389 - frontendIPConfigurationName: 'publicIPConfig1' - frontendPort: 3389 - name: 'inboundNatRule2' - } - ] - loadBalancingRules: [ - { - backendAddressPoolName: 'backendAddressPool1' - backendPort: 80 - disableOutboundSnat: true - enableFloatingIP: false - enableTcpReset: false - frontendIPConfigurationName: 'publicIPConfig1' - frontendPort: 80 - idleTimeoutInMinutes: 5 - loadDistribution: 'Default' - name: 'publicIPLBRule1' - probeName: 'probe1' - protocol: 'Tcp' + outboundRules: [ + { + allocatedOutboundPorts: 63984 + backendAddressPoolName: 'backendAddressPool1' + frontendIPConfigurationName: 'publicIPConfig1' + name: 'outboundRule1' + } + ] + probes: [ + { + intervalInSeconds: 10 + name: 'probe1' + numberOfProbes: 5 + port: 80 + protocol: 'Http' + requestPath: '/http-probe' + } + { + name: 'probe2' + port: 443 + protocol: 'Https' + requestPath: '/https-probe' + } + ] + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - { - backendAddressPoolName: 'backendAddressPool2' - backendPort: 8080 - frontendIPConfigurationName: 'publicIPConfig1' - frontendPort: 8080 - loadDistribution: 'Default' - name: 'publicIPLBRule2' - probeName: 'probe2' - } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' } - outboundRules: [ - { - allocatedOutboundPorts: 63984 - backendAddressPoolName: 'backendAddressPool1' - frontendIPConfigurationName: 'publicIPConfig1' - name: 'outboundRule1' - } - ] - probes: [ - { - intervalInSeconds: 10 - name: 'probe1' - numberOfProbes: 5 - port: 80 - protocol: 'Http' - requestPath: '/http-probe' - } - { - name: 'probe2' - port: 443 - protocol: 'Https' - requestPath: '/https-probe' - } + dependsOn: [ + nestedDependencies + diagnosticDependencies ] - 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' - } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/network/local-network-gateway/main.bicep b/avm/res/network/local-network-gateway/main.bicep index a8ba9836d9..903daef1e4 100644 --- a/avm/res/network/local-network-gateway/main.bicep +++ b/avm/res/network/local-network-gateway/main.bicep @@ -47,30 +47,43 @@ var bgpSettings = { var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + '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') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: take('46d3xbcp.res.network-localnetworkgateway.${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' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: take( + '46d3xbcp.res.network-localnetworkgateway.${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' + } } } } } -} resource localNetworkGateway 'Microsoft.Network/localNetworkGateways@2023-04-01' = { name: name @@ -86,28 +99,37 @@ resource localNetworkGateway 'Microsoft.Network/localNetworkGateways@2023-04-01' } } -resource localNetworkGateway_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.' +resource localNetworkGateway_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: localNetworkGateway } - scope: localNetworkGateway -} -resource localNetworkGateway_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(localNetworkGateway.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource localNetworkGateway_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(localNetworkGateway.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: localNetworkGateway } - scope: localNetworkGateway -}] +] @description('The resource ID of the local network gateway.') output resourceId string = localNetworkGateway.id diff --git a/avm/res/network/local-network-gateway/main.json b/avm/res/network/local-network-gateway/main.json index 2399fd278e..7f9f8f7f80 100644 --- a/avm/res/network/local-network-gateway/main.json +++ b/avm/res/network/local-network-gateway/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11943218028925171301" + "version": "0.26.54.24096", + "templateHash": "8917905061877887283" }, "name": "Local Network Gateways", "description": "This module deploys a Local Network Gateway.", diff --git a/avm/res/network/local-network-gateway/tests/e2e/defaults/main.test.bicep b/avm/res/network/local-network-gateway/tests/e2e/defaults/main.test.bicep index 3d8c1fa7b7..1d3a803c22 100644 --- a/avm/res/network/local-network-gateway/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/local-network-gateway/tests/e2e/defaults/main.test.bicep @@ -36,15 +36,17 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - localAddressPrefixes: [ - '192.168.1.0/24' - ] - localGatewayPublicIpAddress: '8.8.8.8' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + localAddressPrefixes: [ + '192.168.1.0/24' + ] + localGatewayPublicIpAddress: '8.8.8.8' + } } -}] +] diff --git a/avm/res/network/local-network-gateway/tests/e2e/max/dependencies.bicep b/avm/res/network/local-network-gateway/tests/e2e/max/dependencies.bicep index a7f42aee7b..7be39e253a 100644 --- a/avm/res/network/local-network-gateway/tests/e2e/max/dependencies.bicep +++ b/avm/res/network/local-network-gateway/tests/e2e/max/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/network/local-network-gateway/tests/e2e/max/main.test.bicep b/avm/res/network/local-network-gateway/tests/e2e/max/main.test.bicep index e2300f1c24..2fa14fcdba 100644 --- a/avm/res/network/local-network-gateway/tests/e2e/max/main.test.bicep +++ b/avm/res/network/local-network-gateway/tests/e2e/max/main.test.bicep @@ -45,43 +45,48 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - localAddressPrefixes: [ - '192.168.1.0/24' - ] - localGatewayPublicIpAddress: '8.8.8.8' - localAsn: '65123' - localBgpPeeringAddress: '192.168.1.5' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + localAddressPrefixes: [ + '192.168.1.0/24' + ] + localGatewayPublicIpAddress: '8.8.8.8' + localAsn: '65123' + localBgpPeeringAddress: '192.168.1.5' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/network/local-network-gateway/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/local-network-gateway/tests/e2e/waf-aligned/main.test.bicep index 0dacd22889..b2f1caefb6 100644 --- a/avm/res/network/local-network-gateway/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/local-network-gateway/tests/e2e/waf-aligned/main.test.bicep @@ -36,26 +36,28 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - localAddressPrefixes: [ - '192.168.1.0/24' - ] - localGatewayPublicIpAddress: '8.8.8.8' - localAsn: '65123' - localBgpPeeringAddress: '192.168.1.5' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + localAddressPrefixes: [ + '192.168.1.0/24' + ] + localGatewayPublicIpAddress: '8.8.8.8' + localAsn: '65123' + localBgpPeeringAddress: '192.168.1.5' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } } -}] +] diff --git a/avm/res/network/nat-gateway/main.bicep b/avm/res/network/nat-gateway/main.bicep index 0790009605..5dc541069b 100644 --- a/avm/res/network/nat-gateway/main.bicep +++ b/avm/res/network/nat-gateway/main.bicep @@ -40,80 +40,100 @@ param enableTelemetry bool = true var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + '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') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: take('46d3xbcp.res.network-natgateway.${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' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: take( + '46d3xbcp.res.network-natgateway.${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' + } } } } } -} -module publicIPAddresses 'br/public:avm/res/network/public-ip-address:0.2.1' = [for (publicIPAddressObject, index) in (publicIPAddressObjects ?? []): { - name: '${uniqueString(deployment().name, location)}-NatGw-PIP-${index}' - params: { - name: contains(publicIPAddressObject, 'name') ? publicIPAddressObject.name : '${name}-pip' - location: location - lock: publicIPAddressObject.?lock ?? lock - diagnosticSettings: publicIPAddressObject.?diagnosticSettings - publicIPAddressVersion: publicIPAddressObject.?publicIPAddressVersion - publicIPAllocationMethod: 'Static' - publicIpPrefixResourceId: publicIPAddressObject.?publicIPPrefixResourceId - roleAssignments: publicIPAddressObject.?roleAssignments - skuName: 'Standard' // Must be standard - skuTier: publicIPAddressObject.?skuTier - tags: publicIPAddressObject.?tags ?? tags - zones: publicIPAddressObject.?zones - enableTelemetry: publicIPAddressObject.?enableTelemetry ?? enableTelemetry - ddosSettings: publicIPAddressObject.?ddosSettings - dnsSettings: publicIPAddressObject.?dnsSettings - idleTimeoutInMinutes: publicIPAddressObject.?idleTimeoutInMinutes +module publicIPAddresses 'br/public:avm/res/network/public-ip-address:0.2.1' = [ + for (publicIPAddressObject, index) in (publicIPAddressObjects ?? []): { + name: '${uniqueString(deployment().name, location)}-NatGw-PIP-${index}' + params: { + name: contains(publicIPAddressObject, 'name') ? publicIPAddressObject.name : '${name}-pip' + location: location + lock: publicIPAddressObject.?lock ?? lock + diagnosticSettings: publicIPAddressObject.?diagnosticSettings + publicIPAddressVersion: publicIPAddressObject.?publicIPAddressVersion + publicIPAllocationMethod: 'Static' + publicIpPrefixResourceId: publicIPAddressObject.?publicIPPrefixResourceId + roleAssignments: publicIPAddressObject.?roleAssignments + skuName: 'Standard' // Must be standard + skuTier: publicIPAddressObject.?skuTier + tags: publicIPAddressObject.?tags ?? tags + zones: publicIPAddressObject.?zones + enableTelemetry: publicIPAddressObject.?enableTelemetry ?? enableTelemetry + ddosSettings: publicIPAddressObject.?ddosSettings + dnsSettings: publicIPAddressObject.?dnsSettings + idleTimeoutInMinutes: publicIPAddressObject.?idleTimeoutInMinutes + } } -}] +] module formattedPublicIpResourceIds 'modules/formatResourceId.bicep' = { name: 'formattedPublicIpResourceIds' params: { - generatedResourceIds: [for (obj, index) in (publicIPAddressObjects ?? []): publicIPAddresses[index].outputs.resourceId] + generatedResourceIds: [ + for (obj, index) in (publicIPAddressObjects ?? []): publicIPAddresses[index].outputs.resourceId + ] providedResourceIds: publicIpResourceIds } } -module publicIPPrefixes 'br/public:avm/res/network/public-ip-prefix:0.1.0' = [for (publicIPPrefixObject, index) in (publicIPPrefixObjects ?? []): { - name: '${uniqueString(deployment().name, location)}-NatGw-Prefix-PIP-${index}' - params: { - name: contains(publicIPPrefixObject, 'name') ? publicIPPrefixObject.name : '${name}-pip' - location: location - lock: publicIPPrefixObject.?lock ?? lock - prefixLength: publicIPPrefixObject.prefixLength - customIPPrefix: publicIPPrefixObject.?customIPPrefix - roleAssignments: publicIPPrefixObject.?roleAssignments - tags: publicIPPrefixObject.?tags ?? tags - enableTelemetry: publicIPPrefixObject.?enableTelemetry ?? enableTelemetry +module publicIPPrefixes 'br/public:avm/res/network/public-ip-prefix:0.1.0' = [ + for (publicIPPrefixObject, index) in (publicIPPrefixObjects ?? []): { + name: '${uniqueString(deployment().name, location)}-NatGw-Prefix-PIP-${index}' + params: { + name: contains(publicIPPrefixObject, 'name') ? publicIPPrefixObject.name : '${name}-pip' + location: location + lock: publicIPPrefixObject.?lock ?? lock + prefixLength: publicIPPrefixObject.prefixLength + customIPPrefix: publicIPPrefixObject.?customIPPrefix + roleAssignments: publicIPPrefixObject.?roleAssignments + tags: publicIPPrefixObject.?tags ?? tags + enableTelemetry: publicIPPrefixObject.?enableTelemetry ?? enableTelemetry + } } -}] +] module formattedPublicIpPrefixResourceIds 'modules/formatResourceId.bicep' = { name: 'formattedPublicIpPrefixResourceIds' params: { - generatedResourceIds: [for (obj, index) in (publicIPPrefixObjects ?? []): publicIPPrefixes[index].outputs.resourceId] + generatedResourceIds: [ + for (obj, index) in (publicIPPrefixObjects ?? []): publicIPPrefixes[index].outputs.resourceId + ] providedResourceIds: publicIPPrefixResourceIds - } } @@ -134,28 +154,37 @@ resource natGateway 'Microsoft.Network/natGateways@2023-04-01' = { zones: zones } -resource natGateway_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.' +resource natGateway_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: natGateway } - scope: natGateway -} -resource natGateway_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(natGateway.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource natGateway_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(natGateway.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: natGateway } - scope: natGateway -}] +] @description('The name of the NAT Gateway.') output name string = natGateway.name diff --git a/avm/res/network/nat-gateway/main.json b/avm/res/network/nat-gateway/main.json index 73b0856160..7ef467d769 100644 --- a/avm/res/network/nat-gateway/main.json +++ b/avm/res/network/nat-gateway/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "6217805544789578668" + "version": "0.26.54.24096", + "templateHash": "2169153798099388966" }, "name": "NAT Gateways", "description": "This module deploys a NAT Gateway.", @@ -923,8 +923,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "7172917838055782951" + "version": "0.26.54.24096", + "templateHash": "12157242384503109818" } }, "parameters": { @@ -1301,8 +1301,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "7172917838055782951" + "version": "0.26.54.24096", + "templateHash": "12157242384503109818" } }, "parameters": { diff --git a/avm/res/network/nat-gateway/tests/e2e/defaults/main.test.bicep b/avm/res/network/nat-gateway/tests/e2e/defaults/main.test.bicep index 911d92d36f..13f80bf394 100644 --- a/avm/res/network/nat-gateway/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/nat-gateway/tests/e2e/defaults/main.test.bicep @@ -38,12 +38,14 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - // You parameters go here - location: resourceLocation - name: '${namePrefix}${serviceShort}001' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + // You parameters go here + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + } } -}] +] diff --git a/avm/res/network/nat-gateway/tests/e2e/max/dependencies.bicep b/avm/res/network/nat-gateway/tests/e2e/max/dependencies.bicep index a7f42aee7b..7be39e253a 100644 --- a/avm/res/network/nat-gateway/tests/e2e/max/dependencies.bicep +++ b/avm/res/network/nat-gateway/tests/e2e/max/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/network/nat-gateway/tests/e2e/max/main.test.bicep b/avm/res/network/nat-gateway/tests/e2e/max/main.test.bicep index 7f859e396b..8724d4d789 100644 --- a/avm/res/network/nat-gateway/tests/e2e/max/main.test.bicep +++ b/avm/res/network/nat-gateway/tests/e2e/max/main.test.bicep @@ -59,79 +59,87 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - publicIPAddressObjects: [ - { - name: '${namePrefix}${serviceShort}001-pip' - 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' - } - ] - skuTier: 'Regional' - zones: [ - '1' - '2' - '3' - ] - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - } - ] - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + publicIPAddressObjects: [ + { + name: '${namePrefix}${serviceShort}001-pip' + 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' + } + ] + skuTier: 'Regional' + zones: [ + '1' + '2' + '3' + ] + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + } + ] + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/network/nat-gateway/tests/e2e/prefixCombined/main.test.bicep b/avm/res/network/nat-gateway/tests/e2e/prefixCombined/main.test.bicep index 8680b7934d..e92a1f57f8 100644 --- a/avm/res/network/nat-gateway/tests/e2e/prefixCombined/main.test.bicep +++ b/avm/res/network/nat-gateway/tests/e2e/prefixCombined/main.test.bicep @@ -36,20 +36,22 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - publicIPPrefixObjects: [ - { - name: '${namePrefix}${serviceShort}001-pippre' - prefixLength: 30 - tags: { - 'hidden-title': 'CustomTag' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + publicIPPrefixObjects: [ + { + name: '${namePrefix}${serviceShort}001-pippre' + prefixLength: 30 + tags: { + 'hidden-title': 'CustomTag' + } } - } - ] + ] + } } -}] +] diff --git a/avm/res/network/nat-gateway/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/nat-gateway/tests/e2e/waf-aligned/main.test.bicep index 710a0de739..e6097bdc39 100644 --- a/avm/res/network/nat-gateway/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/nat-gateway/tests/e2e/waf-aligned/main.test.bicep @@ -50,45 +50,47 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - publicIPAddressObjects: [ - { - name: '${namePrefix}${serviceShort}001-pip' - skuTier: 'Regional' - zones: [ - '1' - '2' - '3' - ] - 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: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + publicIPAddressObjects: [ + { + name: '${namePrefix}${serviceShort}001-pip' + skuTier: 'Regional' + zones: [ + '1' + '2' + '3' + ] + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/network/network-interface/main.bicep b/avm/res/network/network-interface/main.bicep index 9a7e7cd809..eb33ce7459 100644 --- a/avm/res/network/network-interface/main.bicep +++ b/avm/res/network/network-interface/main.bicep @@ -65,32 +65,48 @@ param diagnosticSettings diagnosticSettingType var 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') - 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'DNS Resolver Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d' + ) + 'DNS Zone Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'befefa01-2a29-4197-83a8-272ff33ce314' + ) + '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') + '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 (Preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-networkinterface.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-networkinterface.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource networkInterface 'Microsoft.Network/networkInterfaces@2023-04-01' = { name: name @@ -100,78 +116,119 @@ resource networkInterface 'Microsoft.Network/networkInterfaces@2023-04-01' = { auxiliaryMode: auxiliaryMode auxiliarySku: auxiliarySku disableTcpStateTracking: disableTcpStateTracking - dnsSettings: !empty(dnsServers) ? { - dnsServers: dnsServers - } : null + dnsSettings: !empty(dnsServers) + ? { + dnsServers: dnsServers + } + : null enableAcceleratedNetworking: enableAcceleratedNetworking enableIPForwarding: enableIPForwarding - networkSecurityGroup: !empty(networkSecurityGroupResourceId) ? { - id: networkSecurityGroupResourceId - } : null - ipConfigurations: [for (ipConfiguration, index) in ipConfigurations: { - name: contains(ipConfiguration, 'name') ? ipConfiguration.name : 'ipconfig0${index + 1}' - properties: { - primary: index == 0 ? true : false - privateIPAllocationMethod: contains(ipConfiguration, 'privateIPAllocationMethod') ? (!empty(ipConfiguration.privateIPAllocationMethod) ? ipConfiguration.privateIPAllocationMethod : null) : null - privateIPAddress: contains(ipConfiguration, 'privateIPAddress') ? (!empty(ipConfiguration.privateIPAddress) ? ipConfiguration.privateIPAddress : null) : null - publicIPAddress: contains(ipConfiguration, 'publicIPAddressResourceId') ? (ipConfiguration.publicIPAddressResourceId != null ? { - id: ipConfiguration.publicIPAddressResourceId - } : null) : null - subnet: { - id: ipConfiguration.subnetResourceId + networkSecurityGroup: !empty(networkSecurityGroupResourceId) + ? { + id: networkSecurityGroupResourceId + } + : null + ipConfigurations: [ + for (ipConfiguration, index) in ipConfigurations: { + name: contains(ipConfiguration, 'name') ? ipConfiguration.name : 'ipconfig0${index + 1}' + properties: { + primary: index == 0 ? true : false + privateIPAllocationMethod: contains(ipConfiguration, 'privateIPAllocationMethod') + ? (!empty(ipConfiguration.privateIPAllocationMethod) ? ipConfiguration.privateIPAllocationMethod : null) + : null + privateIPAddress: contains(ipConfiguration, 'privateIPAddress') + ? (!empty(ipConfiguration.privateIPAddress) ? ipConfiguration.privateIPAddress : null) + : null + publicIPAddress: contains(ipConfiguration, 'publicIPAddressResourceId') + ? (ipConfiguration.publicIPAddressResourceId != null + ? { + id: ipConfiguration.publicIPAddressResourceId + } + : null) + : null + subnet: { + id: ipConfiguration.subnetResourceId + } + loadBalancerBackendAddressPools: contains(ipConfiguration, 'loadBalancerBackendAddressPools') + ? ipConfiguration.loadBalancerBackendAddressPools + : null + applicationSecurityGroups: contains(ipConfiguration, 'applicationSecurityGroups') + ? ipConfiguration.applicationSecurityGroups + : null + applicationGatewayBackendAddressPools: contains(ipConfiguration, 'applicationGatewayBackendAddressPools') + ? ipConfiguration.applicationGatewayBackendAddressPools + : null + gatewayLoadBalancer: contains(ipConfiguration, 'gatewayLoadBalancer') + ? ipConfiguration.gatewayLoadBalancer + : null + loadBalancerInboundNatRules: contains(ipConfiguration, 'loadBalancerInboundNatRules') + ? ipConfiguration.loadBalancerInboundNatRules + : null + privateIPAddressVersion: contains(ipConfiguration, 'privateIPAddressVersion') + ? ipConfiguration.privateIPAddressVersion + : null + virtualNetworkTaps: contains(ipConfiguration, 'virtualNetworkTaps') + ? ipConfiguration.virtualNetworkTaps + : null } - loadBalancerBackendAddressPools: contains(ipConfiguration, 'loadBalancerBackendAddressPools') ? ipConfiguration.loadBalancerBackendAddressPools : null - applicationSecurityGroups: contains(ipConfiguration, 'applicationSecurityGroups') ? ipConfiguration.applicationSecurityGroups : null - applicationGatewayBackendAddressPools: contains(ipConfiguration, 'applicationGatewayBackendAddressPools') ? ipConfiguration.applicationGatewayBackendAddressPools : null - gatewayLoadBalancer: contains(ipConfiguration, 'gatewayLoadBalancer') ? ipConfiguration.gatewayLoadBalancer : null - loadBalancerInboundNatRules: contains(ipConfiguration, 'loadBalancerInboundNatRules') ? ipConfiguration.loadBalancerInboundNatRules : null - privateIPAddressVersion: contains(ipConfiguration, 'privateIPAddressVersion') ? ipConfiguration.privateIPAddressVersion : null - virtualNetworkTaps: contains(ipConfiguration, 'virtualNetworkTaps') ? ipConfiguration.virtualNetworkTaps : null } - }] + ] } } -resource networkInterface_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.' +resource networkInterface_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: networkInterface } - scope: networkInterface -} -resource networkInterface_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource networkInterface_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: networkInterface } - scope: networkInterface -}] - -resource networkInterface_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(networkInterface.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +] + +resource networkInterface_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(networkInterface.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: networkInterface } - scope: networkInterface -}] +] // =========== // // Outputs // diff --git a/avm/res/network/network-interface/main.json b/avm/res/network/network-interface/main.json index 75c70024f7..6854045337 100644 --- a/avm/res/network/network-interface/main.json +++ b/avm/res/network/network-interface/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "6823101790014877132" + "version": "0.26.54.24096", + "templateHash": "2895286572225870929" }, "name": "Network Interface", "description": "This module deploys a Network Interface.", diff --git a/avm/res/network/network-interface/tests/e2e/defaults/main.test.bicep b/avm/res/network/network-interface/tests/e2e/defaults/main.test.bicep index e0df5a7930..eb4bb2e19a 100644 --- a/avm/res/network/network-interface/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/network-interface/tests/e2e/defaults/main.test.bicep @@ -45,20 +45,22 @@ 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 - ipConfigurations: [ - { - name: 'ipconfig01' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - } +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 + ipConfigurations: [ + { + name: 'ipconfig01' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + } + ] + } + dependsOn: [ + nestedDependencies ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/network/network-interface/tests/e2e/max/main.test.bicep b/avm/res/network/network-interface/tests/e2e/max/main.test.bicep index bc599c8317..fd2dd9578f 100644 --- a/avm/res/network/network-interface/tests/e2e/max/main.test.bicep +++ b/avm/res/network/network-interface/tests/e2e/max/main.test.bicep @@ -62,74 +62,79 @@ 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 - ipConfigurations: [ - { - applicationSecurityGroups: [ - { - id: nestedDependencies.outputs.applicationSecurityGroupResourceId - } - ] - loadBalancerBackendAddressPools: [ - { - id: nestedDependencies.outputs.loadBalancerBackendPoolResourceId - } - ] - name: 'ipconfig01' - subnetResourceId: nestedDependencies.outputs.subnetResourceId +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 + ipConfigurations: [ + { + applicationSecurityGroups: [ + { + id: nestedDependencies.outputs.applicationSecurityGroupResourceId + } + ] + loadBalancerBackendAddressPools: [ + { + id: nestedDependencies.outputs.loadBalancerBackendPoolResourceId + } + ] + name: 'ipconfig01' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + } + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + applicationSecurityGroups: [ + { + id: nestedDependencies.outputs.applicationSecurityGroupResourceId + } + ] + } + ] + diagnosticSettings: [ + { + name: 'customSetting' + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - applicationSecurityGroups: [ - { - id: nestedDependencies.outputs.applicationSecurityGroupResourceId - } - ] - } - ] - diagnosticSettings: [ - { - name: 'customSetting' - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' } - 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' - } + dependsOn: [ + nestedDependencies + diagnosticDependencies ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/network/network-interface/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/network-interface/tests/e2e/waf-aligned/main.test.bicep index 90fb9c34d2..68fcd0f904 100644 --- a/avm/res/network/network-interface/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/network-interface/tests/e2e/waf-aligned/main.test.bicep @@ -61,53 +61,55 @@ 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 - ipConfigurations: [ - { - applicationSecurityGroups: [ - { - id: nestedDependencies.outputs.applicationSecurityGroupResourceId - } - ] - loadBalancerBackendAddressPools: [ - { - id: nestedDependencies.outputs.loadBalancerBackendPoolResourceId - } - ] - name: 'ipconfig01' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - } - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - applicationSecurityGroups: [ - { - id: nestedDependencies.outputs.applicationSecurityGroupResourceId - } - ] +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 + ipConfigurations: [ + { + applicationSecurityGroups: [ + { + id: nestedDependencies.outputs.applicationSecurityGroupResourceId + } + ] + loadBalancerBackendAddressPools: [ + { + id: nestedDependencies.outputs.loadBalancerBackendPoolResourceId + } + ] + name: 'ipconfig01' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + } + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + applicationSecurityGroups: [ + { + id: nestedDependencies.outputs.applicationSecurityGroupResourceId + } + ] + } + ] + diagnosticSettings: [ + { + name: 'customSetting' + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - diagnosticSettings: [ - { - name: 'customSetting' - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/network/network-manager/connectivity-configuration/main.json b/avm/res/network/network-manager/connectivity-configuration/main.json index 380332c668..52db1d0faa 100644 --- a/avm/res/network/network-manager/connectivity-configuration/main.json +++ b/avm/res/network/network-manager/connectivity-configuration/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16868761662321894920" + "version": "0.26.54.24096", + "templateHash": "3569964888966454016" }, "name": "Network Manager Connectivity Configurations", "description": "This module deploys a Network Manager Connectivity Configuration.\nConnectivity configurations define hub-and-spoke or mesh topologies applied to one or more network groups.", diff --git a/avm/res/network/network-manager/main.bicep b/avm/res/network/network-manager/main.bicep index 21b3090ac4..e01ce22fe4 100644 --- a/avm/res/network/network-manager/main.bicep +++ b/avm/res/network/network-manager/main.bicep @@ -46,33 +46,52 @@ param enableTelemetry bool = true var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'IPAM Pool Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b3e853f-ad5d-4fb5-a7b8-56a3581c7037') - 'LocalNGFirewallAdministrator role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a8835c7d-b5cb-47fa-b6f0-65ea10ce07a2') - 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'IPAM Pool Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '7b3e853f-ad5d-4fb5-a7b8-56a3581c7037' + ) + 'LocalNGFirewallAdministrator role': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'a8835c7d-b5cb-47fa-b6f0-65ea10ce07a2' + ) + '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') - 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') - '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') + 'Resource Policy Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '36243c78-bf99-498c-9df9-86d9f8d28608' + ) + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-networkmanager.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-networkmanager.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource networkManager 'Microsoft.Network/networkManagers@2023-04-01' = { name: name @@ -85,76 +104,95 @@ resource networkManager 'Microsoft.Network/networkManagers@2023-04-01' = { } } -module networkManager_networkGroups 'network-group/main.bicep' = [for (networkGroup, index) in networkGroups: { - name: '${uniqueString(deployment().name, location)}-NetworkManager-NetworkGroups-${index}' - params: { - name: networkGroup.name - networkManagerName: networkManager.name - description: contains(networkGroup, 'description') ? networkGroup.description : '' - staticMembers: contains(networkGroup, 'staticMembers') ? networkGroup.staticMembers : [] +module networkManager_networkGroups 'network-group/main.bicep' = [ + for (networkGroup, index) in networkGroups: { + name: '${uniqueString(deployment().name, location)}-NetworkManager-NetworkGroups-${index}' + params: { + name: networkGroup.name + networkManagerName: networkManager.name + description: contains(networkGroup, 'description') ? networkGroup.description : '' + staticMembers: contains(networkGroup, 'staticMembers') ? networkGroup.staticMembers : [] + } } -}] - -module networkManager_connectivityConfigurations 'connectivity-configuration/main.bicep' = [for (connectivityConfiguration, index) in connectivityConfigurations: { - name: '${uniqueString(deployment().name, location)}-NetworkManager-ConnectivityConfigurations-${index}' - params: { - name: connectivityConfiguration.name - networkManagerName: networkManager.name - description: contains(connectivityConfiguration, 'description') ? connectivityConfiguration.description : '' - appliesToGroups: connectivityConfiguration.appliesToGroups - connectivityTopology: connectivityConfiguration.connectivityTopology - hubs: contains(connectivityConfiguration, 'hubs') ? connectivityConfiguration.hubs : [] - deleteExistingPeering: contains(connectivityConfiguration, 'hubs') && (connectivityConfiguration.connectivityTopology == 'HubAndSpoke') ? connectivityConfiguration.deleteExistingPeering : 'False' - isGlobal: contains(connectivityConfiguration, 'isGlobal') ? connectivityConfiguration.isGlobal : 'False' +] + +module networkManager_connectivityConfigurations 'connectivity-configuration/main.bicep' = [ + for (connectivityConfiguration, index) in connectivityConfigurations: { + name: '${uniqueString(deployment().name, location)}-NetworkManager-ConnectivityConfigurations-${index}' + params: { + name: connectivityConfiguration.name + networkManagerName: networkManager.name + description: contains(connectivityConfiguration, 'description') ? connectivityConfiguration.description : '' + appliesToGroups: connectivityConfiguration.appliesToGroups + connectivityTopology: connectivityConfiguration.connectivityTopology + hubs: contains(connectivityConfiguration, 'hubs') ? connectivityConfiguration.hubs : [] + deleteExistingPeering: contains(connectivityConfiguration, 'hubs') && (connectivityConfiguration.connectivityTopology == 'HubAndSpoke') + ? connectivityConfiguration.deleteExistingPeering + : 'False' + isGlobal: contains(connectivityConfiguration, 'isGlobal') ? connectivityConfiguration.isGlobal : 'False' + } + dependsOn: networkManager_networkGroups } - dependsOn: networkManager_networkGroups -}] - -module networkManager_scopeConnections 'scope-connection/main.bicep' = [for (scopeConnection, index) in scopeConnections: { - name: '${uniqueString(deployment().name, location)}-NetworkManager-ScopeConnections-${index}' - params: { - name: scopeConnection.name - networkManagerName: networkManager.name - description: scopeConnection.?description - resourceId: scopeConnection.resourceId - tenantId: scopeConnection.tenantId +] + +module networkManager_scopeConnections 'scope-connection/main.bicep' = [ + for (scopeConnection, index) in scopeConnections: { + name: '${uniqueString(deployment().name, location)}-NetworkManager-ScopeConnections-${index}' + params: { + name: scopeConnection.name + networkManagerName: networkManager.name + description: scopeConnection.?description + resourceId: scopeConnection.resourceId + tenantId: scopeConnection.tenantId + } } -}] - -module networkManager_securityAdminConfigurations 'security-admin-configuration/main.bicep' = [for (securityAdminConfiguration, index) in securityAdminConfigurations: { - name: '${uniqueString(deployment().name, location)}-NetworkManager-SecurityAdminConfigurations-${index}' - params: { - name: securityAdminConfiguration.name - networkManagerName: networkManager.name - description: securityAdminConfiguration.?description - applyOnNetworkIntentPolicyBasedServices: securityAdminConfiguration.applyOnNetworkIntentPolicyBasedServices - ruleCollections: securityAdminConfiguration.?ruleCollections +] + +module networkManager_securityAdminConfigurations 'security-admin-configuration/main.bicep' = [ + for (securityAdminConfiguration, index) in securityAdminConfigurations: { + name: '${uniqueString(deployment().name, location)}-NetworkManager-SecurityAdminConfigurations-${index}' + params: { + name: securityAdminConfiguration.name + networkManagerName: networkManager.name + description: securityAdminConfiguration.?description + applyOnNetworkIntentPolicyBasedServices: securityAdminConfiguration.applyOnNetworkIntentPolicyBasedServices + ruleCollections: securityAdminConfiguration.?ruleCollections + } + dependsOn: networkManager_networkGroups } - dependsOn: networkManager_networkGroups -}] - -resource networkManager_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.' +] + +resource networkManager_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: networkManager } - scope: networkManager -} -resource networkManager_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(networkManager.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource networkManager_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(networkManager.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: networkManager } - scope: networkManager -}] +] @sys.description('The resource group the network manager was deployed into.') output resourceGroupName string = resourceGroup().name diff --git a/avm/res/network/network-manager/main.json b/avm/res/network/network-manager/main.json index f5f2ad12ec..f2e598cb60 100644 --- a/avm/res/network/network-manager/main.json +++ b/avm/res/network/network-manager/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "9720522527868870534" + "version": "0.26.54.24096", + "templateHash": "9790133647197956266" }, "name": "Network Managers", "description": "This module deploys a Network Manager.", @@ -307,8 +307,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "6814363898116827751" + "version": "0.26.54.24096", + "templateHash": "4214103423142628663" }, "name": "Network Manager Network Groups", "description": "This module deploys a Network Manager Network Group.\nA network group is a collection of same-type network resources that you can associate with network manager configurations. You can add same-type network resources after you create the network group.", @@ -386,8 +386,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "8599408258770736969" + "version": "0.26.54.24096", + "templateHash": "6637396315337813947" }, "name": "Network Manager Network Group Static Members", "description": "This module deploys a Network Manager Network Group Static Member.\nStatic membership allows you to explicitly add virtual networks to a group by manually selecting individual virtual networks.", @@ -525,8 +525,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16868761662321894920" + "version": "0.26.54.24096", + "templateHash": "3569964888966454016" }, "name": "Network Manager Connectivity Configurations", "description": "This module deploys a Network Manager Connectivity Configuration.\nConnectivity configurations define hub-and-spoke or mesh topologies applied to one or more network groups.", @@ -682,8 +682,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16681369558452798358" + "version": "0.26.54.24096", + "templateHash": "8767540456657043434" }, "name": "Network Manager Scope Connections", "description": "This module deploys a Network Manager Scope Connection.\nCreate a cross-tenant connection to manage a resource from another tenant.", @@ -801,8 +801,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "7700094852777954431" + "version": "0.26.54.24096", + "templateHash": "254507184583897429" }, "name": "Network Manager Security Admin Configurations", "description": "This module deploys an Network Manager Security Admin Configuration.\nA security admin configuration contains a set of rule collections. Each rule collection contains one or more security admin rules.", @@ -896,8 +896,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "6205777935004784732" + "version": "0.26.54.24096", + "templateHash": "14135307535635501181" }, "name": "Network Manager Security Admin Configuration Rule Collections", "description": "This module deploys an Network Manager Security Admin Configuration Rule Collection.\nA security admin configuration contains a set of rule collections. Each rule collection contains one or more security admin rules. Security admin rules allows enforcing security policy criteria that matches the conditions set. Warning: A rule collection without rule will cause a deployment configuration for security admin goal state in network manager to fail.", @@ -1004,8 +1004,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4678937950332023656" + "version": "0.26.54.24096", + "templateHash": "3477492114570114110" }, "name": "Network Manager Security Admin Configuration Rule Collection Rules", "description": "This module deploys an Azure Virtual Network Manager (AVNM) Security Admin Configuration Rule Collection Rule.\nA security admin configuration contains a set of rule collections. Each rule collection contains one or more security admin rules.", diff --git a/avm/res/network/network-manager/network-group/main.bicep b/avm/res/network/network-manager/network-group/main.bicep index f3540354dd..83ae24b489 100644 --- a/avm/res/network/network-manager/network-group/main.bicep +++ b/avm/res/network/network-manager/network-group/main.bicep @@ -29,15 +29,17 @@ resource networkGroup 'Microsoft.Network/networkManagers/networkGroups@2023-04-0 } } -module networkGroup_staticMembers 'static-member/main.bicep' = [for (staticMember, index) in staticMembers: { - name: '${uniqueString(deployment().name)}-NetworkGroup-StaticMembers-${index}' - params: { - networkManagerName: networkManager.name - networkGroupName: networkGroup.name - name: staticMember.name - resourceId: staticMember.resourceId +module networkGroup_staticMembers 'static-member/main.bicep' = [ + for (staticMember, index) in staticMembers: { + name: '${uniqueString(deployment().name)}-NetworkGroup-StaticMembers-${index}' + params: { + networkManagerName: networkManager.name + networkGroupName: networkGroup.name + name: staticMember.name + resourceId: staticMember.resourceId + } } -}] +] @sys.description('The name of the deployed network group.') output name string = networkGroup.name diff --git a/avm/res/network/network-manager/network-group/main.json b/avm/res/network/network-manager/network-group/main.json index 1530879d81..97b0f3c631 100644 --- a/avm/res/network/network-manager/network-group/main.json +++ b/avm/res/network/network-manager/network-group/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "6814363898116827751" + "version": "0.26.54.24096", + "templateHash": "4214103423142628663" }, "name": "Network Manager Network Groups", "description": "This module deploys a Network Manager Network Group.\nA network group is a collection of same-type network resources that you can associate with network manager configurations. You can add same-type network resources after you create the network group.", @@ -83,8 +83,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "8599408258770736969" + "version": "0.26.54.24096", + "templateHash": "6637396315337813947" }, "name": "Network Manager Network Group Static Members", "description": "This module deploys a Network Manager Network Group Static Member.\nStatic membership allows you to explicitly add virtual networks to a group by manually selecting individual virtual networks.", diff --git a/avm/res/network/network-manager/network-group/static-member/main.json b/avm/res/network/network-manager/network-group/static-member/main.json index 6d345d55e4..5bcd72dbb6 100644 --- a/avm/res/network/network-manager/network-group/static-member/main.json +++ b/avm/res/network/network-manager/network-group/static-member/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "8599408258770736969" + "version": "0.26.54.24096", + "templateHash": "6637396315337813947" }, "name": "Network Manager Network Group Static Members", "description": "This module deploys a Network Manager Network Group Static Member.\nStatic membership allows you to explicitly add virtual networks to a group by manually selecting individual virtual networks.", diff --git a/avm/res/network/network-manager/scope-connection/main.json b/avm/res/network/network-manager/scope-connection/main.json index a3cd1c3c1d..ec1b947129 100644 --- a/avm/res/network/network-manager/scope-connection/main.json +++ b/avm/res/network/network-manager/scope-connection/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16681369558452798358" + "version": "0.26.54.24096", + "templateHash": "8767540456657043434" }, "name": "Network Manager Scope Connections", "description": "This module deploys a Network Manager Scope Connection.\nCreate a cross-tenant connection to manage a resource from another tenant.", diff --git a/avm/res/network/network-manager/security-admin-configuration/main.bicep b/avm/res/network/network-manager/security-admin-configuration/main.bicep index ee23d8dc66..f18e53140d 100644 --- a/avm/res/network/network-manager/security-admin-configuration/main.bicep +++ b/avm/res/network/network-manager/security-admin-configuration/main.bicep @@ -20,7 +20,7 @@ param description string = '' 'AllowRulesOnly' ]) @sys.description('Required. Enum list of network intent policy based services.') -param applyOnNetworkIntentPolicyBasedServices array = [ 'None' ] +param applyOnNetworkIntentPolicyBasedServices array = ['None'] @sys.description('Optional. A security admin configuration contains a set of rule collections that are applied to network groups. Each rule collection contains one or more security admin rules.') param ruleCollections array = [] @@ -38,16 +38,18 @@ resource securityAdminConfigurations 'Microsoft.Network/networkManagers/security } } -module securityAdminConfigurations_ruleCollections 'rule-collection/main.bicep' = [for (ruleCollection, index) in ruleCollections: { - name: '${uniqueString(deployment().name)}-SecurityAdminConfigurations-RuleCollections-${index}' - params: { - networkManagerName: networkManager.name - securityAdminConfigurationName: securityAdminConfigurations.name - name: ruleCollection.name - appliesToGroups: ruleCollection.appliesToGroups - rules: contains(ruleCollection, 'rules') ? ruleCollection.rules : [] +module securityAdminConfigurations_ruleCollections 'rule-collection/main.bicep' = [ + for (ruleCollection, index) in ruleCollections: { + name: '${uniqueString(deployment().name)}-SecurityAdminConfigurations-RuleCollections-${index}' + params: { + networkManagerName: networkManager.name + securityAdminConfigurationName: securityAdminConfigurations.name + name: ruleCollection.name + appliesToGroups: ruleCollection.appliesToGroups + rules: contains(ruleCollection, 'rules') ? ruleCollection.rules : [] + } } -}] +] @sys.description('The name of the deployed security admin configuration.') output name string = securityAdminConfigurations.name diff --git a/avm/res/network/network-manager/security-admin-configuration/main.json b/avm/res/network/network-manager/security-admin-configuration/main.json index ae70ce5dd7..a81e94c390 100644 --- a/avm/res/network/network-manager/security-admin-configuration/main.json +++ b/avm/res/network/network-manager/security-admin-configuration/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "7700094852777954431" + "version": "0.26.54.24096", + "templateHash": "254507184583897429" }, "name": "Network Manager Security Admin Configurations", "description": "This module deploys an Network Manager Security Admin Configuration.\nA security admin configuration contains a set of rule collections. Each rule collection contains one or more security admin rules.", @@ -99,8 +99,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "6205777935004784732" + "version": "0.26.54.24096", + "templateHash": "14135307535635501181" }, "name": "Network Manager Security Admin Configuration Rule Collections", "description": "This module deploys an Network Manager Security Admin Configuration Rule Collection.\nA security admin configuration contains a set of rule collections. Each rule collection contains one or more security admin rules. Security admin rules allows enforcing security policy criteria that matches the conditions set. Warning: A rule collection without rule will cause a deployment configuration for security admin goal state in network manager to fail.", @@ -207,8 +207,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4678937950332023656" + "version": "0.26.54.24096", + "templateHash": "3477492114570114110" }, "name": "Network Manager Security Admin Configuration Rule Collection Rules", "description": "This module deploys an Azure Virtual Network Manager (AVNM) Security Admin Configuration Rule Collection Rule.\nA security admin configuration contains a set of rule collections. Each rule collection contains one or more security admin rules.", diff --git a/avm/res/network/network-manager/security-admin-configuration/rule-collection/main.bicep b/avm/res/network/network-manager/security-admin-configuration/rule-collection/main.bicep index c248ef811a..0d46003890 100644 --- a/avm/res/network/network-manager/security-admin-configuration/rule-collection/main.bicep +++ b/avm/res/network/network-manager/security-admin-configuration/rule-collection/main.bicep @@ -40,24 +40,26 @@ resource ruleCollection 'Microsoft.Network/networkManagers/securityAdminConfigur } } -module securityAdminConfigurations_rules 'rule/main.bicep' = [for (rule, index) in rules: { - name: '${uniqueString(deployment().name)}-RuleCollections-Rules-${index}' - params: { - networkManagerName: networkManager.name - securityAdminConfigurationName: securityAdminConfigurationName - ruleCollectionName: ruleCollection.name - name: rule.name - access: rule.access - description: contains(rule, 'description') ? rule.description : '' - destinationPortRanges: contains(rule, 'destinationPortRanges') ? rule.destinationPortRanges : [] - destinations: contains(rule, 'destinations') ? rule.destinations : [] - direction: rule.direction - priority: rule.priority - protocol: rule.protocol - sourcePortRanges: contains(rule, 'sourcePortRanges') ? rule.sourcePortRanges : [] - sources: contains(rule, 'sources') ? rule.sources : [] +module securityAdminConfigurations_rules 'rule/main.bicep' = [ + for (rule, index) in rules: { + name: '${uniqueString(deployment().name)}-RuleCollections-Rules-${index}' + params: { + networkManagerName: networkManager.name + securityAdminConfigurationName: securityAdminConfigurationName + ruleCollectionName: ruleCollection.name + name: rule.name + access: rule.access + description: contains(rule, 'description') ? rule.description : '' + destinationPortRanges: contains(rule, 'destinationPortRanges') ? rule.destinationPortRanges : [] + destinations: contains(rule, 'destinations') ? rule.destinations : [] + direction: rule.direction + priority: rule.priority + protocol: rule.protocol + sourcePortRanges: contains(rule, 'sourcePortRanges') ? rule.sourcePortRanges : [] + sources: contains(rule, 'sources') ? rule.sources : [] + } } -}] +] @sys.description('The name of the deployed admin rule collection.') output name string = ruleCollection.name diff --git a/avm/res/network/network-manager/security-admin-configuration/rule-collection/main.json b/avm/res/network/network-manager/security-admin-configuration/rule-collection/main.json index 3307d5b494..2c2b95d8c0 100644 --- a/avm/res/network/network-manager/security-admin-configuration/rule-collection/main.json +++ b/avm/res/network/network-manager/security-admin-configuration/rule-collection/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "6205777935004784732" + "version": "0.26.54.24096", + "templateHash": "14135307535635501181" }, "name": "Network Manager Security Admin Configuration Rule Collections", "description": "This module deploys an Network Manager Security Admin Configuration Rule Collection.\nA security admin configuration contains a set of rule collections. Each rule collection contains one or more security admin rules. Security admin rules allows enforcing security policy criteria that matches the conditions set. Warning: A rule collection without rule will cause a deployment configuration for security admin goal state in network manager to fail.", @@ -112,8 +112,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4678937950332023656" + "version": "0.26.54.24096", + "templateHash": "3477492114570114110" }, "name": "Network Manager Security Admin Configuration Rule Collection Rules", "description": "This module deploys an Azure Virtual Network Manager (AVNM) Security Admin Configuration Rule Collection Rule.\nA security admin configuration contains a set of rule collections. Each rule collection contains one or more security admin rules.", diff --git a/avm/res/network/network-manager/security-admin-configuration/rule-collection/rule/main.json b/avm/res/network/network-manager/security-admin-configuration/rule-collection/rule/main.json index 83f21a1945..c45d77c10f 100644 --- a/avm/res/network/network-manager/security-admin-configuration/rule-collection/rule/main.json +++ b/avm/res/network/network-manager/security-admin-configuration/rule-collection/rule/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4678937950332023656" + "version": "0.26.54.24096", + "templateHash": "3477492114570114110" }, "name": "Network Manager Security Admin Configuration Rule Collection Rules", "description": "This module deploys an Azure Virtual Network Manager (AVNM) Security Admin Configuration Rule Collection Rule.\nA security admin configuration contains a set of rule collections. Each rule collection contains one or more security admin rules.", diff --git a/avm/res/network/network-manager/tests/e2e/defaults/main.test.bicep b/avm/res/network/network-manager/tests/e2e/defaults/main.test.bicep index e7494fcccd..ed65356e84 100644 --- a/avm/res/network/network-manager/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/network-manager/tests/e2e/defaults/main.test.bicep @@ -36,19 +36,21 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 - networkManagerScopeAccesses: [ - 'Connectivity' - ] - networkManagerScopes: { - subscriptions: [ - subscription().id +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 + networkManagerScopeAccesses: [ + 'Connectivity' ] + networkManagerScopes: { + subscriptions: [ + subscription().id + ] + } } } -}] +] diff --git a/avm/res/network/network-manager/tests/e2e/max/main.test.bicep b/avm/res/network/network-manager/tests/e2e/max/main.test.bicep index d6a524f1ba..2c1ebd6b50 100644 --- a/avm/res/network/network-manager/tests/e2e/max/main.test.bicep +++ b/avm/res/network/network-manager/tests/e2e/max/main.test.bicep @@ -51,217 +51,222 @@ var networkManagerName = '${namePrefix}${serviceShort}001' var networkManagerExpecetedResourceID = '${resourceGroup.id}/providers/Microsoft.Network/networkManagers/${networkManagerName}' @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - name: networkManagerName - location: resourceLocation - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: networkManagerName + location: resourceLocation + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - 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' - } - ] - networkManagerScopeAccesses: [ - 'Connectivity' - 'SecurityAdmin' - ] - networkManagerScopes: { - managementGroups: [ - // Note: Required the `Microsoft.Network` provider to be registered at management group level via `az provider register --namespace Microsoft.Network -m ''` - '/providers/Microsoft.Management/managementGroups/#_managementGroupId_#' + 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' + } ] - } - networkGroups: [ - { - name: 'network-group-spokes' - description: 'network-group-spokes description' - staticMembers: [ - { - name: 'virtualNetworkSpoke1' - resourceId: nestedDependencies.outputs.virtualNetworkSpoke1Id - } - { - name: 'virtualNetworkSpoke2' - resourceId: nestedDependencies.outputs.virtualNetworkSpoke2Id - } - ] - } - ] - connectivityConfigurations: [ - { - name: 'hubSpokeConnectivity' - description: 'hubSpokeConnectivity description' - connectivityTopology: 'HubAndSpoke' - hubs: [ - { - resourceId: nestedDependencies.outputs.virtualNetworkHubId - resourceType: 'Microsoft.Network/virtualNetworks' - } - ] - deleteExistingPeering: 'True' - isGlobal: 'True' - appliesToGroups: [ - { - networkGroupId: '${networkManagerExpecetedResourceID}/networkGroups/network-group-spokes' - useHubGateway: 'False' - groupConnectivity: 'None' - isGlobal: 'False' - } - ] - } - { - name: 'MeshConnectivity' - description: 'MeshConnectivity description' - connectivityTopology: 'Mesh' - deleteExistingPeering: 'True' - isGlobal: 'True' - appliesToGroups: [ - { - networkGroupId: '${networkManagerExpecetedResourceID}/networkGroups/network-group-spokes' - useHubGateway: 'False' - groupConnectivity: 'None' - isGlobal: 'False' - } + networkManagerScopeAccesses: [ + 'Connectivity' + 'SecurityAdmin' + ] + networkManagerScopes: { + managementGroups: [ + // Note: Required the `Microsoft.Network` provider to be registered at management group level via `az provider register --namespace Microsoft.Network -m ''` + '/providers/Microsoft.Management/managementGroups/#_managementGroupId_#' ] } - ] - scopeConnections: [ - { - name: 'scope-connection-test' - description: 'description of the scope connection' - resourceId: subscription().id - tenantid: tenant().tenantId - } - ] - securityAdminConfigurations: [ - { - name: 'test-security-admin-config' - description: 'description of the security admin config' - applyOnNetworkIntentPolicyBasedServices: [ - 'AllowRulesOnly' - ] - ruleCollections: [ - { - name: 'test-rule-collection-1' - description: 'test-rule-collection-description' - appliesToGroups: [ - { - networkGroupId: '${networkManagerExpecetedResourceID}/networkGroups/network-group-spokes' - } - ] - rules: [ - { - name: 'test-inbound-allow-rule-1' - description: 'test-inbound-allow-rule-1-description' - access: 'Allow' - direction: 'Inbound' - priority: 150 - protocol: 'Tcp' - } - { - name: 'test-outbound-deny-rule-2' - description: 'test-outbound-deny-rule-2-description' - access: 'Deny' - direction: 'Outbound' - priority: 200 - protocol: 'Tcp' - sourcePortRanges: [ - '80' - '442-445' - ] - sources: [ - { - addressPrefix: 'AppService.WestEurope' - addressPrefixType: 'ServiceTag' - } - ] - } - ] - } - { - name: 'test-rule-collection-2' - description: 'test-rule-collection-description' - appliesToGroups: [ - { - networkGroupId: '${networkManagerExpecetedResourceID}/networkGroups/network-group-spokes' - } - ] - rules: [ - { - name: 'test-inbound-allow-rule-3' - description: 'test-inbound-allow-rule-3-description' - access: 'Allow' - direction: 'Inbound' - destinationPortRanges: [ - '80' - '442-445' - ] - destinations: [ - { - addressPrefix: '192.168.20.20' - addressPrefixType: 'IPPrefix' - } - ] - priority: 250 - protocol: 'Tcp' - } - { - name: 'test-inbound-allow-rule-4' - description: 'test-inbound-allow-rule-4-description' - access: 'Allow' - direction: 'Inbound' - sources: [ - { - addressPrefix: '10.0.0.0/24' - addressPrefixType: 'IPPrefix' - } - { - addressPrefix: '100.100.100.100' - addressPrefixType: 'IPPrefix' - } - ] - destinations: [ - { - addressPrefix: '172.16.0.0/24' - addressPrefixType: 'IPPrefix' - } - { - addressPrefix: '172.16.1.0/24' - addressPrefixType: 'IPPrefix' - } - ] - priority: 260 - protocol: 'Tcp' - } - ] - } - ] + networkGroups: [ + { + name: 'network-group-spokes' + description: 'network-group-spokes description' + staticMembers: [ + { + name: 'virtualNetworkSpoke1' + resourceId: nestedDependencies.outputs.virtualNetworkSpoke1Id + } + { + name: 'virtualNetworkSpoke2' + resourceId: nestedDependencies.outputs.virtualNetworkSpoke2Id + } + ] + } + ] + connectivityConfigurations: [ + { + name: 'hubSpokeConnectivity' + description: 'hubSpokeConnectivity description' + connectivityTopology: 'HubAndSpoke' + hubs: [ + { + resourceId: nestedDependencies.outputs.virtualNetworkHubId + resourceType: 'Microsoft.Network/virtualNetworks' + } + ] + deleteExistingPeering: 'True' + isGlobal: 'True' + appliesToGroups: [ + { + networkGroupId: '${networkManagerExpecetedResourceID}/networkGroups/network-group-spokes' + useHubGateway: 'False' + groupConnectivity: 'None' + isGlobal: 'False' + } + ] + } + { + name: 'MeshConnectivity' + description: 'MeshConnectivity description' + connectivityTopology: 'Mesh' + deleteExistingPeering: 'True' + isGlobal: 'True' + appliesToGroups: [ + { + networkGroupId: '${networkManagerExpecetedResourceID}/networkGroups/network-group-spokes' + useHubGateway: 'False' + groupConnectivity: 'None' + isGlobal: 'False' + } + ] + } + ] + scopeConnections: [ + { + name: 'scope-connection-test' + description: 'description of the scope connection' + resourceId: subscription().id + tenantid: tenant().tenantId + } + ] + securityAdminConfigurations: [ + { + name: 'test-security-admin-config' + description: 'description of the security admin config' + applyOnNetworkIntentPolicyBasedServices: [ + 'AllowRulesOnly' + ] + ruleCollections: [ + { + name: 'test-rule-collection-1' + description: 'test-rule-collection-description' + appliesToGroups: [ + { + networkGroupId: '${networkManagerExpecetedResourceID}/networkGroups/network-group-spokes' + } + ] + rules: [ + { + name: 'test-inbound-allow-rule-1' + description: 'test-inbound-allow-rule-1-description' + access: 'Allow' + direction: 'Inbound' + priority: 150 + protocol: 'Tcp' + } + { + name: 'test-outbound-deny-rule-2' + description: 'test-outbound-deny-rule-2-description' + access: 'Deny' + direction: 'Outbound' + priority: 200 + protocol: 'Tcp' + sourcePortRanges: [ + '80' + '442-445' + ] + sources: [ + { + addressPrefix: 'AppService.WestEurope' + addressPrefixType: 'ServiceTag' + } + ] + } + ] + } + { + name: 'test-rule-collection-2' + description: 'test-rule-collection-description' + appliesToGroups: [ + { + networkGroupId: '${networkManagerExpecetedResourceID}/networkGroups/network-group-spokes' + } + ] + rules: [ + { + name: 'test-inbound-allow-rule-3' + description: 'test-inbound-allow-rule-3-description' + access: 'Allow' + direction: 'Inbound' + destinationPortRanges: [ + '80' + '442-445' + ] + destinations: [ + { + addressPrefix: '192.168.20.20' + addressPrefixType: 'IPPrefix' + } + ] + priority: 250 + protocol: 'Tcp' + } + { + name: 'test-inbound-allow-rule-4' + description: 'test-inbound-allow-rule-4-description' + access: 'Allow' + direction: 'Inbound' + sources: [ + { + addressPrefix: '10.0.0.0/24' + addressPrefixType: 'IPPrefix' + } + { + addressPrefix: '100.100.100.100' + addressPrefixType: 'IPPrefix' + } + ] + destinations: [ + { + addressPrefix: '172.16.0.0/24' + addressPrefixType: 'IPPrefix' + } + { + addressPrefix: '172.16.1.0/24' + addressPrefixType: 'IPPrefix' + } + ] + priority: 260 + protocol: 'Tcp' + } + ] + } + ] + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/network/network-manager/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/network-manager/tests/e2e/waf-aligned/main.test.bicep index d52a6465e3..1d025f410c 100644 --- a/avm/res/network/network-manager/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/network-manager/tests/e2e/waf-aligned/main.test.bicep @@ -36,24 +36,26 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { // ============== // @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 - networkManagerScopeAccesses: [ - 'SecurityAdmin' - ] - networkManagerScopes: { - subscriptions: [ - subscription().id +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 + networkManagerScopeAccesses: [ + 'SecurityAdmin' ] - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + networkManagerScopes: { + subscriptions: [ + subscription().id + ] + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } } -}] +] diff --git a/avm/res/network/network-security-group/main.bicep b/avm/res/network/network-security-group/main.bicep index b91fa4c876..153ff53214 100644 --- a/avm/res/network/network-security-group/main.bicep +++ b/avm/res/network/network-security-group/main.bicep @@ -31,30 +31,40 @@ param enableTelemetry bool = true var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + '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') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-networksecuritygroup.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-networksecuritygroup.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2023-04-01' = { name: name @@ -62,92 +72,152 @@ resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2023-04-0 tags: tags properties: { flushConnection: flushConnection - securityRules: [for securityRule in securityRules: { - name: securityRule.name - properties: { - protocol: securityRule.properties.protocol - access: securityRule.properties.access - priority: securityRule.properties.priority - direction: securityRule.properties.direction - description: contains(securityRule.properties, 'description') ? securityRule.properties.description : '' - sourcePortRange: contains(securityRule.properties, 'sourcePortRange') ? securityRule.properties.sourcePortRange : '' - sourcePortRanges: contains(securityRule.properties, 'sourcePortRanges') ? securityRule.properties.sourcePortRanges : [] - destinationPortRange: contains(securityRule.properties, 'destinationPortRange') ? securityRule.properties.destinationPortRange : '' - destinationPortRanges: contains(securityRule.properties, 'destinationPortRanges') ? securityRule.properties.destinationPortRanges : [] - sourceAddressPrefix: contains(securityRule.properties, 'sourceAddressPrefix') ? securityRule.properties.sourceAddressPrefix : '' - destinationAddressPrefix: contains(securityRule.properties, 'destinationAddressPrefix') ? securityRule.properties.destinationAddressPrefix : '' - sourceAddressPrefixes: contains(securityRule.properties, 'sourceAddressPrefixes') ? securityRule.properties.sourceAddressPrefixes : [] - destinationAddressPrefixes: contains(securityRule.properties, 'destinationAddressPrefixes') ? securityRule.properties.destinationAddressPrefixes : [] - sourceApplicationSecurityGroups: contains(securityRule.properties, 'sourceApplicationSecurityGroups') ? securityRule.properties.sourceApplicationSecurityGroups : [] - destinationApplicationSecurityGroups: contains(securityRule.properties, 'destinationApplicationSecurityGroups') ? securityRule.properties.destinationApplicationSecurityGroups : [] + securityRules: [ + for securityRule in securityRules: { + name: securityRule.name + properties: { + protocol: securityRule.properties.protocol + access: securityRule.properties.access + priority: securityRule.properties.priority + direction: securityRule.properties.direction + description: contains(securityRule.properties, 'description') ? securityRule.properties.description : '' + sourcePortRange: contains(securityRule.properties, 'sourcePortRange') + ? securityRule.properties.sourcePortRange + : '' + sourcePortRanges: contains(securityRule.properties, 'sourcePortRanges') + ? securityRule.properties.sourcePortRanges + : [] + destinationPortRange: contains(securityRule.properties, 'destinationPortRange') + ? securityRule.properties.destinationPortRange + : '' + destinationPortRanges: contains(securityRule.properties, 'destinationPortRanges') + ? securityRule.properties.destinationPortRanges + : [] + sourceAddressPrefix: contains(securityRule.properties, 'sourceAddressPrefix') + ? securityRule.properties.sourceAddressPrefix + : '' + destinationAddressPrefix: contains(securityRule.properties, 'destinationAddressPrefix') + ? securityRule.properties.destinationAddressPrefix + : '' + sourceAddressPrefixes: contains(securityRule.properties, 'sourceAddressPrefixes') + ? securityRule.properties.sourceAddressPrefixes + : [] + destinationAddressPrefixes: contains(securityRule.properties, 'destinationAddressPrefixes') + ? securityRule.properties.destinationAddressPrefixes + : [] + sourceApplicationSecurityGroups: contains(securityRule.properties, 'sourceApplicationSecurityGroups') + ? securityRule.properties.sourceApplicationSecurityGroups + : [] + destinationApplicationSecurityGroups: contains( + securityRule.properties, + 'destinationApplicationSecurityGroups' + ) + ? securityRule.properties.destinationApplicationSecurityGroups + : [] + } } - }] + ] } } -module networkSecurityGroup_securityRules 'security-rule/main.bicep' = [for (securityRule, index) in securityRules: { - name: '${uniqueString(deployment().name, location)}-NetworkSecurityGroup-SecurityRule-${index}' - params: { - name: securityRule.name - networkSecurityGroupName: networkSecurityGroup.name - protocol: securityRule.properties.protocol - access: securityRule.properties.access - priority: securityRule.properties.priority - direction: securityRule.properties.direction - description: contains(securityRule.properties, 'description') ? securityRule.properties.description : '' - sourcePortRange: contains(securityRule.properties, 'sourcePortRange') ? securityRule.properties.sourcePortRange : '' - sourcePortRanges: contains(securityRule.properties, 'sourcePortRanges') ? securityRule.properties.sourcePortRanges : [] - destinationPortRange: contains(securityRule.properties, 'destinationPortRange') ? securityRule.properties.destinationPortRange : '' - destinationPortRanges: contains(securityRule.properties, 'destinationPortRanges') ? securityRule.properties.destinationPortRanges : [] - sourceAddressPrefix: contains(securityRule.properties, 'sourceAddressPrefix') ? securityRule.properties.sourceAddressPrefix : '' - destinationAddressPrefix: contains(securityRule.properties, 'destinationAddressPrefix') ? securityRule.properties.destinationAddressPrefix : '' - sourceAddressPrefixes: contains(securityRule.properties, 'sourceAddressPrefixes') ? securityRule.properties.sourceAddressPrefixes : [] - destinationAddressPrefixes: contains(securityRule.properties, 'destinationAddressPrefixes') ? securityRule.properties.destinationAddressPrefixes : [] - sourceApplicationSecurityGroups: contains(securityRule.properties, 'sourceApplicationSecurityGroups') ? securityRule.properties.sourceApplicationSecurityGroups : [] - destinationApplicationSecurityGroups: contains(securityRule.properties, 'destinationApplicationSecurityGroups') ? securityRule.properties.destinationApplicationSecurityGroups : [] +module networkSecurityGroup_securityRules 'security-rule/main.bicep' = [ + for (securityRule, index) in securityRules: { + name: '${uniqueString(deployment().name, location)}-NetworkSecurityGroup-SecurityRule-${index}' + params: { + name: securityRule.name + networkSecurityGroupName: networkSecurityGroup.name + protocol: securityRule.properties.protocol + access: securityRule.properties.access + priority: securityRule.properties.priority + direction: securityRule.properties.direction + description: contains(securityRule.properties, 'description') ? securityRule.properties.description : '' + sourcePortRange: contains(securityRule.properties, 'sourcePortRange') + ? securityRule.properties.sourcePortRange + : '' + sourcePortRanges: contains(securityRule.properties, 'sourcePortRanges') + ? securityRule.properties.sourcePortRanges + : [] + destinationPortRange: contains(securityRule.properties, 'destinationPortRange') + ? securityRule.properties.destinationPortRange + : '' + destinationPortRanges: contains(securityRule.properties, 'destinationPortRanges') + ? securityRule.properties.destinationPortRanges + : [] + sourceAddressPrefix: contains(securityRule.properties, 'sourceAddressPrefix') + ? securityRule.properties.sourceAddressPrefix + : '' + destinationAddressPrefix: contains(securityRule.properties, 'destinationAddressPrefix') + ? securityRule.properties.destinationAddressPrefix + : '' + sourceAddressPrefixes: contains(securityRule.properties, 'sourceAddressPrefixes') + ? securityRule.properties.sourceAddressPrefixes + : [] + destinationAddressPrefixes: contains(securityRule.properties, 'destinationAddressPrefixes') + ? securityRule.properties.destinationAddressPrefixes + : [] + sourceApplicationSecurityGroups: contains(securityRule.properties, 'sourceApplicationSecurityGroups') + ? securityRule.properties.sourceApplicationSecurityGroups + : [] + destinationApplicationSecurityGroups: contains(securityRule.properties, 'destinationApplicationSecurityGroups') + ? securityRule.properties.destinationApplicationSecurityGroups + : [] + } } -}] - -resource networkSecurityGroup_lock 'Microsoft.Authorization/locks@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.' +] + +resource networkSecurityGroup_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: networkSecurityGroup } - scope: networkSecurityGroup -} -resource networkSecurityGroup_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource networkSecurityGroup_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: networkSecurityGroup } - scope: networkSecurityGroup -}] - -resource networkSecurityGroup_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(networkSecurityGroup.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +] + +resource networkSecurityGroup_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(networkSecurityGroup.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: networkSecurityGroup } - scope: networkSecurityGroup -}] +] @description('The resource group the network security group was deployed into.') output resourceGroupName string = resourceGroup().name diff --git a/avm/res/network/network-security-group/main.json b/avm/res/network/network-security-group/main.json index 5c6096e566..f260b58df4 100644 --- a/avm/res/network/network-security-group/main.json +++ b/avm/res/network/network-security-group/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4216984327038707510" + "version": "0.26.54.24096", + "templateHash": "3515627050133600386" }, "name": "Network Security Groups", "description": "This module deploys a Network security Group (NSG).", @@ -446,8 +446,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "7870858269129613686" + "version": "0.26.54.24096", + "templateHash": "5675009765675721781" }, "name": "Network Security Group (NSG) Security Rules", "description": "This module deploys a Network Security Group (NSG) Security Rule.", diff --git a/avm/res/network/network-security-group/security-rule/main.json b/avm/res/network/network-security-group/security-rule/main.json index f2e48de864..c0aaac0c4b 100644 --- a/avm/res/network/network-security-group/security-rule/main.json +++ b/avm/res/network/network-security-group/security-rule/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "7870858269129613686" + "version": "0.26.54.24096", + "templateHash": "5675009765675721781" }, "name": "Network Security Group (NSG) Security Rules", "description": "This module deploys a Network Security Group (NSG) Security Rule.", diff --git a/avm/res/network/network-security-group/tests/e2e/defaults/main.test.bicep b/avm/res/network/network-security-group/tests/e2e/defaults/main.test.bicep index 4778e3177b..29e1730be0 100644 --- a/avm/res/network/network-security-group/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/network-security-group/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 +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 + } } -}] +] diff --git a/avm/res/network/network-security-group/tests/e2e/max/main.test.bicep b/avm/res/network/network-security-group/tests/e2e/max/main.test.bicep index eeba0435d6..74d43232b8 100644 --- a/avm/res/network/network-security-group/tests/e2e/max/main.test.bicep +++ b/avm/res/network/network-security-group/tests/e2e/max/main.test.bicep @@ -60,114 +60,119 @@ 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 - diagnosticSettings: [ - { - name: 'customSetting' - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - 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' - } - ] - securityRules: [ - { - name: 'Specific' - properties: { - access: 'Allow' - description: 'Tests specific IPs and ports' - destinationAddressPrefix: '*' - destinationPortRange: '8080' - direction: 'Inbound' - priority: 100 - protocol: '*' - sourceAddressPrefix: '*' - sourcePortRange: '*' +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 + diagnosticSettings: [ + { + name: 'customSetting' + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - name: 'Ranges' - properties: { - access: 'Allow' - description: 'Tests Ranges' - destinationAddressPrefixes: [ - '10.2.0.0/16' - '10.3.0.0/16' - ] - destinationPortRanges: [ - '90' - '91' - ] - direction: 'Inbound' - priority: 101 - protocol: '*' - sourceAddressPrefixes: [ - '10.0.0.0/16' - '10.1.0.0/16' - ] - sourcePortRanges: [ - '80' - '81' - ] + roleAssignments: [ + { + roleDefinitionIdOrName: 'Owner' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' } - } - { - name: 'Port_8082' - properties: { - access: 'Allow' - description: 'Allow inbound access on TCP 8082' - destinationApplicationSecurityGroups: [ - { - id: nestedDependencies.outputs.applicationSecurityGroupResourceId - } - ] - destinationPortRange: '8082' - direction: 'Inbound' - priority: 102 - protocol: '*' - sourceApplicationSecurityGroups: [ - { - id: nestedDependencies.outputs.applicationSecurityGroupResourceId - } - ] - sourcePortRange: '*' + { + 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' + } + ] + securityRules: [ + { + name: 'Specific' + properties: { + access: 'Allow' + description: 'Tests specific IPs and ports' + destinationAddressPrefix: '*' + destinationPortRange: '8080' + direction: 'Inbound' + priority: 100 + protocol: '*' + sourceAddressPrefix: '*' + sourcePortRange: '*' + } } + { + name: 'Ranges' + properties: { + access: 'Allow' + description: 'Tests Ranges' + destinationAddressPrefixes: [ + '10.2.0.0/16' + '10.3.0.0/16' + ] + destinationPortRanges: [ + '90' + '91' + ] + direction: 'Inbound' + priority: 101 + protocol: '*' + sourceAddressPrefixes: [ + '10.0.0.0/16' + '10.1.0.0/16' + ] + sourcePortRanges: [ + '80' + '81' + ] + } + } + { + name: 'Port_8082' + properties: { + access: 'Allow' + description: 'Allow inbound access on TCP 8082' + destinationApplicationSecurityGroups: [ + { + id: nestedDependencies.outputs.applicationSecurityGroupResourceId + } + ] + destinationPortRange: '8082' + direction: 'Inbound' + priority: 102 + protocol: '*' + sourceApplicationSecurityGroups: [ + { + id: nestedDependencies.outputs.applicationSecurityGroupResourceId + } + ] + sourcePortRange: '*' + } + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/network/network-security-group/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/network-security-group/tests/e2e/waf-aligned/main.test.bicep index 9e413ec922..5a5e8f1669 100644 --- a/avm/res/network/network-security-group/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/network-security-group/tests/e2e/waf-aligned/main.test.bicep @@ -59,97 +59,99 @@ 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 - diagnosticSettings: [ - { - name: 'customSetting' - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - securityRules: [ - { - name: 'Specific' - properties: { - access: 'Allow' - description: 'Tests specific IPs and ports' - destinationAddressPrefix: '*' - destinationPortRange: '8080' - direction: 'Inbound' - priority: 100 - protocol: '*' - sourceAddressPrefix: '*' - sourcePortRange: '*' +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 + diagnosticSettings: [ + { + name: 'customSetting' + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - name: 'Ranges' - properties: { - access: 'Allow' - description: 'Tests Ranges' - destinationAddressPrefixes: [ - '10.2.0.0/16' - '10.3.0.0/16' - ] - destinationPortRanges: [ - '90' - '91' - ] - direction: 'Inbound' - priority: 101 - protocol: '*' - sourceAddressPrefixes: [ - '10.0.0.0/16' - '10.1.0.0/16' - ] - sourcePortRanges: [ - '80' - '81' - ] + securityRules: [ + { + name: 'Specific' + properties: { + access: 'Allow' + description: 'Tests specific IPs and ports' + destinationAddressPrefix: '*' + destinationPortRange: '8080' + direction: 'Inbound' + priority: 100 + protocol: '*' + sourceAddressPrefix: '*' + sourcePortRange: '*' + } } - } - { - name: 'Port_8082' - properties: { - access: 'Allow' - description: 'Allow inbound access on TCP 8082' - destinationApplicationSecurityGroups: [ - { - id: nestedDependencies.outputs.applicationSecurityGroupResourceId - } - ] - destinationPortRange: '8082' - direction: 'Inbound' - priority: 102 - protocol: '*' - sourceApplicationSecurityGroups: [ - { - id: nestedDependencies.outputs.applicationSecurityGroupResourceId - } - ] - sourcePortRange: '*' + { + name: 'Ranges' + properties: { + access: 'Allow' + description: 'Tests Ranges' + destinationAddressPrefixes: [ + '10.2.0.0/16' + '10.3.0.0/16' + ] + destinationPortRanges: [ + '90' + '91' + ] + direction: 'Inbound' + priority: 101 + protocol: '*' + sourceAddressPrefixes: [ + '10.0.0.0/16' + '10.1.0.0/16' + ] + sourcePortRanges: [ + '80' + '81' + ] + } + } + { + name: 'Port_8082' + properties: { + access: 'Allow' + description: 'Allow inbound access on TCP 8082' + destinationApplicationSecurityGroups: [ + { + id: nestedDependencies.outputs.applicationSecurityGroupResourceId + } + ] + destinationPortRange: '8082' + direction: 'Inbound' + priority: 102 + protocol: '*' + sourceApplicationSecurityGroups: [ + { + id: nestedDependencies.outputs.applicationSecurityGroupResourceId + } + ] + sourcePortRange: '*' + } } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/network/private-dns-zone/a/main.bicep b/avm/res/network/private-dns-zone/a/main.bicep index 8d6c525711..9804d60427 100644 --- a/avm/res/network/private-dns-zone/a/main.bicep +++ b/avm/res/network/private-dns-zone/a/main.bicep @@ -22,12 +22,24 @@ param roleAssignments roleAssignmentType var 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') + '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') + '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' + ) } resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { @@ -44,19 +56,25 @@ resource A 'Microsoft.Network/privateDnsZones/A@2020-06-01' = { } } -resource A_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(A.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource A_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(A.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: A } - scope: A -}] +] @description('The name of the deployed A record.') output name string = A.name diff --git a/avm/res/network/private-dns-zone/a/main.json b/avm/res/network/private-dns-zone/a/main.json index 81f4e9fa80..0a939afdf2 100644 --- a/avm/res/network/private-dns-zone/a/main.json +++ b/avm/res/network/private-dns-zone/a/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17565463524922013743" + "version": "0.26.54.24096", + "templateHash": "12306956034851223701" }, "name": "Private DNS Zone A record", "description": "This module deploys a Private DNS Zone A record.", diff --git a/avm/res/network/private-dns-zone/aaaa/main.bicep b/avm/res/network/private-dns-zone/aaaa/main.bicep index 180e605405..00c814df6a 100644 --- a/avm/res/network/private-dns-zone/aaaa/main.bicep +++ b/avm/res/network/private-dns-zone/aaaa/main.bicep @@ -22,12 +22,24 @@ param roleAssignments roleAssignmentType var 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') + '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') + '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' + ) } resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { @@ -44,19 +56,25 @@ resource AAAA 'Microsoft.Network/privateDnsZones/AAAA@2020-06-01' = { } } -resource AAAA_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(AAAA.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource AAAA_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(AAAA.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: AAAA } - scope: AAAA -}] +] @description('The name of the deployed AAAA record.') output name string = AAAA.name diff --git a/avm/res/network/private-dns-zone/aaaa/main.json b/avm/res/network/private-dns-zone/aaaa/main.json index 00732682f0..86ca4b5bfc 100644 --- a/avm/res/network/private-dns-zone/aaaa/main.json +++ b/avm/res/network/private-dns-zone/aaaa/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14360797759459973436" + "version": "0.26.54.24096", + "templateHash": "15517532978293030748" }, "name": "Private DNS Zone AAAA record", "description": "This module deploys a Private DNS Zone AAAA record.", diff --git a/avm/res/network/private-dns-zone/cname/main.bicep b/avm/res/network/private-dns-zone/cname/main.bicep index 8e63c47f7f..a3923729b5 100644 --- a/avm/res/network/private-dns-zone/cname/main.bicep +++ b/avm/res/network/private-dns-zone/cname/main.bicep @@ -22,12 +22,24 @@ param roleAssignments roleAssignmentType var 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') + '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') + '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' + ) } resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { @@ -44,19 +56,25 @@ resource CNAME 'Microsoft.Network/privateDnsZones/CNAME@2020-06-01' = { } } -resource CNAME_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(CNAME.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource CNAME_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(CNAME.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: CNAME } - scope: CNAME -}] +] @description('The name of the deployed CNAME record.') output name string = CNAME.name diff --git a/avm/res/network/private-dns-zone/cname/main.json b/avm/res/network/private-dns-zone/cname/main.json index f590f488aa..25f8fd4f6e 100644 --- a/avm/res/network/private-dns-zone/cname/main.json +++ b/avm/res/network/private-dns-zone/cname/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "8360937786294538789" + "version": "0.26.54.24096", + "templateHash": "4178056552366181250" }, "name": "Private DNS Zone CNAME record", "description": "This module deploys a Private DNS Zone CNAME record.", diff --git a/avm/res/network/private-dns-zone/main.bicep b/avm/res/network/private-dns-zone/main.bicep index 28881fb037..8d79e045dd 100644 --- a/avm/res/network/private-dns-zone/main.bicep +++ b/avm/res/network/private-dns-zone/main.bicep @@ -49,30 +49,40 @@ param enableTelemetry bool = true var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + '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') + '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 (Preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-privatednszone.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-privatednszone.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { name: name @@ -80,136 +90,163 @@ resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { tags: tags } -module privateDnsZone_A 'a/main.bicep' = [for (aRecord, index) in (a ?? []): { - name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-ARecord-${index}' - params: { - privateDnsZoneName: privateDnsZone.name - name: aRecord.name - aRecords: aRecord.?aRecords - metadata: aRecord.?metadata - ttl: aRecord.?ttl ?? 3600 - roleAssignments: aRecord.?roleAssignments +module privateDnsZone_A 'a/main.bicep' = [ + for (aRecord, index) in (a ?? []): { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-ARecord-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: aRecord.name + aRecords: aRecord.?aRecords + metadata: aRecord.?metadata + ttl: aRecord.?ttl ?? 3600 + roleAssignments: aRecord.?roleAssignments + } } -}] - -module privateDnsZone_AAAA 'aaaa/main.bicep' = [for (aaaaRecord, index) in (aaaa ?? []): { - name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-AAAARecord-${index}' - params: { - privateDnsZoneName: privateDnsZone.name - name: aaaaRecord.name - aaaaRecords: aaaaRecord.?aaaaRecords - metadata: aaaaRecord.?metadata - ttl: aaaaRecord.?ttl ?? 3600 - roleAssignments: aaaaRecord.?roleAssignments +] + +module privateDnsZone_AAAA 'aaaa/main.bicep' = [ + for (aaaaRecord, index) in (aaaa ?? []): { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-AAAARecord-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: aaaaRecord.name + aaaaRecords: aaaaRecord.?aaaaRecords + metadata: aaaaRecord.?metadata + ttl: aaaaRecord.?ttl ?? 3600 + roleAssignments: aaaaRecord.?roleAssignments + } } -}] - -module privateDnsZone_CNAME 'cname/main.bicep' = [for (cnameRecord, index) in (cname ?? []): { - name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-CNAMERecord-${index}' - params: { - privateDnsZoneName: privateDnsZone.name - name: cnameRecord.name - cnameRecord: cnameRecord.?cnameRecord - metadata: cnameRecord.?metadata - ttl: cnameRecord.?ttl ?? 3600 - roleAssignments: cnameRecord.?roleAssignments +] + +module privateDnsZone_CNAME 'cname/main.bicep' = [ + for (cnameRecord, index) in (cname ?? []): { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-CNAMERecord-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: cnameRecord.name + cnameRecord: cnameRecord.?cnameRecord + metadata: cnameRecord.?metadata + ttl: cnameRecord.?ttl ?? 3600 + roleAssignments: cnameRecord.?roleAssignments + } } -}] - -module privateDnsZone_MX 'mx/main.bicep' = [for (mxRecord, index) in (mx ?? []): { - name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-MXRecord-${index}' - params: { - privateDnsZoneName: privateDnsZone.name - name: mxRecord.name - metadata: mxRecord.?metadata - mxRecords: mxRecord.?mxRecords - ttl: mxRecord.?ttl ?? 3600 - roleAssignments: mxRecord.?roleAssignments +] + +module privateDnsZone_MX 'mx/main.bicep' = [ + for (mxRecord, index) in (mx ?? []): { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-MXRecord-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: mxRecord.name + metadata: mxRecord.?metadata + mxRecords: mxRecord.?mxRecords + ttl: mxRecord.?ttl ?? 3600 + roleAssignments: mxRecord.?roleAssignments + } } -}] - -module privateDnsZone_PTR 'ptr/main.bicep' = [for (ptrRecord, index) in (ptr ?? []): { - name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-PTRRecord-${index}' - params: { - privateDnsZoneName: privateDnsZone.name - name: ptrRecord.name - metadata: ptrRecord.?metadata - ptrRecords: ptrRecord.?ptrRecords - ttl: ptrRecord.?ttl ?? 3600 - roleAssignments: ptrRecord.?roleAssignments +] + +module privateDnsZone_PTR 'ptr/main.bicep' = [ + for (ptrRecord, index) in (ptr ?? []): { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-PTRRecord-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: ptrRecord.name + metadata: ptrRecord.?metadata + ptrRecords: ptrRecord.?ptrRecords + ttl: ptrRecord.?ttl ?? 3600 + roleAssignments: ptrRecord.?roleAssignments + } } -}] - -module privateDnsZone_SOA 'soa/main.bicep' = [for (soaRecord, index) in (soa ?? []): { - name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-SOARecord-${index}' - params: { - privateDnsZoneName: privateDnsZone.name - name: soaRecord.name - metadata: soaRecord.?metadata - soaRecord: soaRecord.?soaRecord - ttl: soaRecord.?ttl ?? 3600 - roleAssignments: soaRecord.?roleAssignments +] + +module privateDnsZone_SOA 'soa/main.bicep' = [ + for (soaRecord, index) in (soa ?? []): { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-SOARecord-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: soaRecord.name + metadata: soaRecord.?metadata + soaRecord: soaRecord.?soaRecord + ttl: soaRecord.?ttl ?? 3600 + roleAssignments: soaRecord.?roleAssignments + } } -}] - -module privateDnsZone_SRV 'srv/main.bicep' = [for (srvRecord, index) in (srv ?? []): { - name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-SRVRecord-${index}' - params: { - privateDnsZoneName: privateDnsZone.name - name: srvRecord.name - metadata: srvRecord.?metadata - srvRecords: srvRecord.?srvRecords - ttl: srvRecord.?ttl ?? 3600 - roleAssignments: srvRecord.?roleAssignments +] + +module privateDnsZone_SRV 'srv/main.bicep' = [ + for (srvRecord, index) in (srv ?? []): { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-SRVRecord-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: srvRecord.name + metadata: srvRecord.?metadata + srvRecords: srvRecord.?srvRecords + ttl: srvRecord.?ttl ?? 3600 + roleAssignments: srvRecord.?roleAssignments + } } -}] - -module privateDnsZone_TXT 'txt/main.bicep' = [for (txtRecord, index) in (txt ?? []): { - name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-TXTRecord-${index}' - params: { - privateDnsZoneName: privateDnsZone.name - name: txtRecord.name - metadata: txtRecord.?metadata - txtRecords: txtRecord.?txtRecords - ttl: txtRecord.?ttl ?? 3600 - roleAssignments: txtRecord.?roleAssignments +] + +module privateDnsZone_TXT 'txt/main.bicep' = [ + for (txtRecord, index) in (txt ?? []): { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-TXTRecord-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: txtRecord.name + metadata: txtRecord.?metadata + txtRecords: txtRecord.?txtRecords + ttl: txtRecord.?ttl ?? 3600 + roleAssignments: txtRecord.?roleAssignments + } } -}] - -module privateDnsZone_virtualNetworkLinks 'virtual-network-link/main.bicep' = [for (virtualNetworkLink, index) in (virtualNetworkLinks ?? []): { - name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-VirtualNetworkLink-${index}' - params: { - privateDnsZoneName: privateDnsZone.name - name: virtualNetworkLink.?name ?? '${last(split(virtualNetworkLink.virtualNetworkResourceId, '/'))}-vnetlink' - virtualNetworkResourceId: virtualNetworkLink.virtualNetworkResourceId - location: virtualNetworkLink.?location ?? 'global' - registrationEnabled: virtualNetworkLink.?registrationEnabled ?? false - tags: virtualNetworkLink.?tags ?? tags +] + +module privateDnsZone_virtualNetworkLinks 'virtual-network-link/main.bicep' = [ + for (virtualNetworkLink, index) in (virtualNetworkLinks ?? []): { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-VirtualNetworkLink-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: virtualNetworkLink.?name ?? '${last(split(virtualNetworkLink.virtualNetworkResourceId, '/'))}-vnetlink' + virtualNetworkResourceId: virtualNetworkLink.virtualNetworkResourceId + location: virtualNetworkLink.?location ?? 'global' + registrationEnabled: virtualNetworkLink.?registrationEnabled ?? false + tags: virtualNetworkLink.?tags ?? tags + } } -}] - -resource privateDnsZone_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.' +] + +resource privateDnsZone_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: privateDnsZone } - scope: privateDnsZone -} -resource privateDnsZone_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(privateDnsZone.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource privateDnsZone_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(privateDnsZone.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: privateDnsZone } - scope: privateDnsZone -}] +] @description('The resource group the private DNS zone was deployed into.') output resourceGroupName string = resourceGroup().name diff --git a/avm/res/network/private-dns-zone/main.json b/avm/res/network/private-dns-zone/main.json index 73b572a650..c8c39f4fd6 100644 --- a/avm/res/network/private-dns-zone/main.json +++ b/avm/res/network/private-dns-zone/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "5015696597887719627" + "version": "0.26.54.24096", + "templateHash": "3327242936340774578" }, "name": "Private DNS Zones", "description": "This module deploys a Private DNS zone.", @@ -323,8 +323,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17565463524922013743" + "version": "0.26.54.24096", + "templateHash": "12306956034851223701" }, "name": "Private DNS Zone A record", "description": "This module deploys a Private DNS Zone A record.", @@ -562,8 +562,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14360797759459973436" + "version": "0.26.54.24096", + "templateHash": "15517532978293030748" }, "name": "Private DNS Zone AAAA record", "description": "This module deploys a Private DNS Zone AAAA record.", @@ -801,8 +801,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "8360937786294538789" + "version": "0.26.54.24096", + "templateHash": "4178056552366181250" }, "name": "Private DNS Zone CNAME record", "description": "This module deploys a Private DNS Zone CNAME record.", @@ -1040,8 +1040,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17929107555284027881" + "version": "0.26.54.24096", + "templateHash": "10977884265298427114" }, "name": "Private DNS Zone MX record", "description": "This module deploys a Private DNS Zone MX record.", @@ -1279,8 +1279,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "5937391315050932617" + "version": "0.26.54.24096", + "templateHash": "10561246444555326733" }, "name": "Private DNS Zone PTR record", "description": "This module deploys a Private DNS Zone PTR record.", @@ -1518,8 +1518,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "15774595998971084317" + "version": "0.26.54.24096", + "templateHash": "17840534414219914835" }, "name": "Private DNS Zone SOA record", "description": "This module deploys a Private DNS Zone SOA record.", @@ -1757,8 +1757,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "6637703638195225114" + "version": "0.26.54.24096", + "templateHash": "17625006509638611979" }, "name": "Private DNS Zone SRV record", "description": "This module deploys a Private DNS Zone SRV record.", @@ -1996,8 +1996,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4386552419329587852" + "version": "0.26.54.24096", + "templateHash": "1962752727391912227" }, "name": "Private DNS Zone TXT record", "description": "This module deploys a Private DNS Zone TXT record.", @@ -2235,8 +2235,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2508137843266136274" + "version": "0.26.54.24096", + "templateHash": "8223766852442158769" }, "name": "Private DNS Zone Virtual Network Link", "description": "This module deploys a Private DNS Zone Virtual Network Link.", diff --git a/avm/res/network/private-dns-zone/mx/main.bicep b/avm/res/network/private-dns-zone/mx/main.bicep index f0f4e5a09e..3430a6af63 100644 --- a/avm/res/network/private-dns-zone/mx/main.bicep +++ b/avm/res/network/private-dns-zone/mx/main.bicep @@ -22,12 +22,24 @@ param roleAssignments roleAssignmentType var 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') + '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') + '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' + ) } resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { @@ -44,19 +56,25 @@ resource MX 'Microsoft.Network/privateDnsZones/MX@2020-06-01' = { } } -resource MX_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(MX.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource MX_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(MX.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: MX } - scope: MX -}] +] @description('The name of the deployed MX record.') output name string = MX.name diff --git a/avm/res/network/private-dns-zone/mx/main.json b/avm/res/network/private-dns-zone/mx/main.json index 651880a641..70582965b0 100644 --- a/avm/res/network/private-dns-zone/mx/main.json +++ b/avm/res/network/private-dns-zone/mx/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17929107555284027881" + "version": "0.26.54.24096", + "templateHash": "10977884265298427114" }, "name": "Private DNS Zone MX record", "description": "This module deploys a Private DNS Zone MX record.", diff --git a/avm/res/network/private-dns-zone/ptr/main.bicep b/avm/res/network/private-dns-zone/ptr/main.bicep index f4fda1e300..7343b754fb 100644 --- a/avm/res/network/private-dns-zone/ptr/main.bicep +++ b/avm/res/network/private-dns-zone/ptr/main.bicep @@ -22,12 +22,24 @@ param roleAssignments roleAssignmentType var 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') + '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') + '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' + ) } resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { @@ -44,19 +56,25 @@ resource PTR 'Microsoft.Network/privateDnsZones/PTR@2020-06-01' = { } } -resource PTR_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(PTR.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource PTR_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(PTR.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: PTR } - scope: PTR -}] +] @description('The name of the deployed PTR record.') output name string = PTR.name diff --git a/avm/res/network/private-dns-zone/ptr/main.json b/avm/res/network/private-dns-zone/ptr/main.json index 1f2c165b04..59abe7528d 100644 --- a/avm/res/network/private-dns-zone/ptr/main.json +++ b/avm/res/network/private-dns-zone/ptr/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "5937391315050932617" + "version": "0.26.54.24096", + "templateHash": "10561246444555326733" }, "name": "Private DNS Zone PTR record", "description": "This module deploys a Private DNS Zone PTR record.", diff --git a/avm/res/network/private-dns-zone/soa/main.bicep b/avm/res/network/private-dns-zone/soa/main.bicep index ef56247adf..34f5b558da 100644 --- a/avm/res/network/private-dns-zone/soa/main.bicep +++ b/avm/res/network/private-dns-zone/soa/main.bicep @@ -22,12 +22,24 @@ param roleAssignments roleAssignmentType var 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') + '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') + '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' + ) } resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { @@ -44,19 +56,25 @@ resource SOA 'Microsoft.Network/privateDnsZones/SOA@2020-06-01' = { } } -resource SOA_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(SOA.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource SOA_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(SOA.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: SOA } - scope: SOA -}] +] @description('The name of the deployed SOA record.') output name string = SOA.name diff --git a/avm/res/network/private-dns-zone/soa/main.json b/avm/res/network/private-dns-zone/soa/main.json index 700024ee9b..4c7ca7fb2f 100644 --- a/avm/res/network/private-dns-zone/soa/main.json +++ b/avm/res/network/private-dns-zone/soa/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "15774595998971084317" + "version": "0.26.54.24096", + "templateHash": "17840534414219914835" }, "name": "Private DNS Zone SOA record", "description": "This module deploys a Private DNS Zone SOA record.", diff --git a/avm/res/network/private-dns-zone/srv/main.bicep b/avm/res/network/private-dns-zone/srv/main.bicep index 1ab0c2cbfc..55e55a56d1 100644 --- a/avm/res/network/private-dns-zone/srv/main.bicep +++ b/avm/res/network/private-dns-zone/srv/main.bicep @@ -22,12 +22,24 @@ param roleAssignments roleAssignmentType var 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') + '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') + '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' + ) } resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { @@ -44,19 +56,25 @@ resource SRV 'Microsoft.Network/privateDnsZones/SRV@2020-06-01' = { } } -resource SRV_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(SRV.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource SRV_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(SRV.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: SRV } - scope: SRV -}] +] @description('The name of the deployed SRV record.') output name string = SRV.name diff --git a/avm/res/network/private-dns-zone/srv/main.json b/avm/res/network/private-dns-zone/srv/main.json index 3d34cfa3fe..2406f41be8 100644 --- a/avm/res/network/private-dns-zone/srv/main.json +++ b/avm/res/network/private-dns-zone/srv/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "6637703638195225114" + "version": "0.26.54.24096", + "templateHash": "17625006509638611979" }, "name": "Private DNS Zone SRV record", "description": "This module deploys a Private DNS Zone SRV record.", diff --git a/avm/res/network/private-dns-zone/tests/e2e/defaults/main.test.bicep b/avm/res/network/private-dns-zone/tests/e2e/defaults/main.test.bicep index af279b6aa2..81053892b8 100644 --- a/avm/res/network/private-dns-zone/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/private-dns-zone/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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.com' - location: 'global' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001.com' + location: 'global' + } } -}] +] diff --git a/avm/res/network/private-dns-zone/tests/e2e/max/main.test.bicep b/avm/res/network/private-dns-zone/tests/e2e/max/main.test.bicep index e95348146f..d6aa67e9a2 100644 --- a/avm/res/network/private-dns-zone/tests/e2e/max/main.test.bicep +++ b/avm/res/network/private-dns-zone/tests/e2e/max/main.test.bicep @@ -46,258 +46,284 @@ 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.com' - location: 'global' - a: [ - { - aRecords: [ - { - ipv4Address: '10.240.4.4' - } - ] - name: 'A_10.240.4.4' - 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' - } - ] - ttl: 3600 - } - ] - aaaa: [ - { - aaaaRecords: [ - { - ipv6Address: '2001:0db8:85a3:0000:0000:8a2e:0370:7334' - } - ] - name: 'AAAA_2001_0db8_85a3_0000_0000_8a2e_0370_7334' - ttl: 3600 - } - ] - cname: [ - { - cnameRecord: { - cname: 'test' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001.com' + location: 'global' + a: [ + { + aRecords: [ + { + ipv4Address: '10.240.4.4' + } + ] + name: 'A_10.240.4.4' + 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' + } + ] + ttl: 3600 } - name: 'CNAME_test' - 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' - } - ] - ttl: 3600 - } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - mx: [ - { - mxRecords: [ - { - exchange: 'contoso.com' - preference: 100 - } - ] - name: 'MX_contoso' - 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' - } - ] - ttl: 3600 - } - ] - ptr: [ - { - name: 'PTR_contoso' - ptrRecords: [ - { - ptrdname: 'contoso.com' - } - ] - 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' - } - ] - ttl: 3600 - } - ] - 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' - } - ] - soa: [ - { - name: '@' - 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' - } - ] - soaRecord: { - email: 'azureprivatedns-host.microsoft.com' - expireTime: 2419200 - host: 'azureprivatedns.net' - minimumTtl: 10 - refreshTime: 3600 - retryTime: 300 - serialNumber: '1' + ] + aaaa: [ + { + aaaaRecords: [ + { + ipv6Address: '2001:0db8:85a3:0000:0000:8a2e:0370:7334' + } + ] + name: 'AAAA_2001_0db8_85a3_0000_0000_8a2e_0370_7334' + ttl: 3600 } - ttl: 3600 - } - ] - srv: [ - { - name: 'SRV_contoso' - 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' + ] + cname: [ + { + cnameRecord: { + cname: 'test' } - ] - srvRecords: [ - { - port: 9332 - priority: 0 - target: 'test.contoso.com' - weight: 0 - } - ] - ttl: 3600 + name: 'CNAME_test' + 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' + } + ] + ttl: 3600 + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - txt: [ - { - name: 'TXT_test' - 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' - } - ] - ttl: 3600 - txtRecords: [ - { - value: [ - 'test' - ] + mx: [ + { + mxRecords: [ + { + exchange: 'contoso.com' + preference: 100 + } + ] + name: 'MX_contoso' + 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' + } + ] + ttl: 3600 + } + ] + ptr: [ + { + name: 'PTR_contoso' + ptrRecords: [ + { + ptrdname: 'contoso.com' + } + ] + 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' + } + ] + ttl: 3600 + } + ] + 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' + } + ] + soa: [ + { + name: '@' + 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' + } + ] + soaRecord: { + email: 'azureprivatedns-host.microsoft.com' + expireTime: 2419200 + host: 'azureprivatedns.net' + minimumTtl: 10 + refreshTime: 3600 + retryTime: 300 + serialNumber: '1' } - ] - } - ] - virtualNetworkLinks: [ - { - registrationEnabled: true - virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId + ttl: 3600 + } + ] + srv: [ + { + name: 'SRV_contoso' + 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' + } + ] + srvRecords: [ + { + port: 9332 + priority: 0 + target: 'test.contoso.com' + weight: 0 + } + ] + ttl: 3600 + } + ] + txt: [ + { + name: 'TXT_test' + 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' + } + ] + ttl: 3600 + txtRecords: [ + { + value: [ + 'test' + ] + } + ] + } + ] + virtualNetworkLinks: [ + { + registrationEnabled: true + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/network/private-dns-zone/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/private-dns-zone/tests/e2e/waf-aligned/main.test.bicep index cad9a29cfc..465cc291d3 100644 --- a/avm/res/network/private-dns-zone/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/private-dns-zone/tests/e2e/waf-aligned/main.test.bicep @@ -46,20 +46,22 @@ 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.com' - location: 'global' - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001.com' + location: 'global' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } } } -}] +] diff --git a/avm/res/network/private-dns-zone/txt/main.bicep b/avm/res/network/private-dns-zone/txt/main.bicep index 04989c7146..e472ee984b 100644 --- a/avm/res/network/private-dns-zone/txt/main.bicep +++ b/avm/res/network/private-dns-zone/txt/main.bicep @@ -22,12 +22,24 @@ param roleAssignments roleAssignmentType var 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') + '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') + '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' + ) } resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { @@ -44,19 +56,25 @@ resource TXT 'Microsoft.Network/privateDnsZones/TXT@2020-06-01' = { } } -resource TXT_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(TXT.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource TXT_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(TXT.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: TXT } - scope: TXT -}] +] @description('The name of the deployed TXT record.') output name string = TXT.name diff --git a/avm/res/network/private-dns-zone/txt/main.json b/avm/res/network/private-dns-zone/txt/main.json index f5f483986d..c3747524ef 100644 --- a/avm/res/network/private-dns-zone/txt/main.json +++ b/avm/res/network/private-dns-zone/txt/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4386552419329587852" + "version": "0.26.54.24096", + "templateHash": "1962752727391912227" }, "name": "Private DNS Zone TXT record", "description": "This module deploys a Private DNS Zone TXT record.", diff --git a/avm/res/network/private-dns-zone/virtual-network-link/main.json b/avm/res/network/private-dns-zone/virtual-network-link/main.json index 0591440aad..4c6a56a124 100644 --- a/avm/res/network/private-dns-zone/virtual-network-link/main.json +++ b/avm/res/network/private-dns-zone/virtual-network-link/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2508137843266136274" + "version": "0.26.54.24096", + "templateHash": "8223766852442158769" }, "name": "Private DNS Zone Virtual Network Link", "description": "This module deploys a Private DNS Zone Virtual Network Link.", diff --git a/avm/res/network/private-endpoint/main.bicep b/avm/res/network/private-endpoint/main.bicep index 2a3fc9de61..84caddce5b 100644 --- a/avm/res/network/private-endpoint/main.bicep +++ b/avm/res/network/private-endpoint/main.bicep @@ -49,43 +49,67 @@ param enableTelemetry bool = true var 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') + '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') + '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 (Preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-privateendpoint.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-privateendpoint.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource privateEndpoint 'Microsoft.Network/privateEndpoints@2023-04-01' = { name: name location: location tags: tags properties: { - applicationSecurityGroups: [for applicationSecurityGroupResourceId in (applicationSecurityGroupResourceIds ?? []): { - id: applicationSecurityGroupResourceId - }] + applicationSecurityGroups: [ + for applicationSecurityGroupResourceId in (applicationSecurityGroupResourceIds ?? []): { + id: applicationSecurityGroupResourceId + } + ] customDnsConfigs: customDnsConfigs ?? [] customNetworkInterfaceName: customNetworkInterfaceName ?? '' ipConfigurations: ipConfigurations ?? [] @@ -97,37 +121,47 @@ resource privateEndpoint 'Microsoft.Network/privateEndpoints@2023-04-01' = { } } -module privateEndpoint_privateDnsZoneGroup 'private-dns-zone-group/main.bicep' = if (!empty(privateDnsZoneResourceIds)) { - name: '${uniqueString(deployment().name)}-PrivateEndpoint-PrivateDnsZoneGroup' - params: { - name: privateDnsZoneGroupName ?? 'default' - privateDNSResourceIds: privateDnsZoneResourceIds ?? [] - privateEndpointName: privateEndpoint.name +module privateEndpoint_privateDnsZoneGroup 'private-dns-zone-group/main.bicep' = + if (!empty(privateDnsZoneResourceIds)) { + name: '${uniqueString(deployment().name)}-PrivateEndpoint-PrivateDnsZoneGroup' + params: { + name: privateDnsZoneGroupName ?? 'default' + privateDNSResourceIds: privateDnsZoneResourceIds ?? [] + privateEndpointName: privateEndpoint.name + } } -} -resource privateEndpoint_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.' +resource privateEndpoint_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: privateEndpoint } - scope: privateEndpoint -} -resource privateEndpoint_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(privateEndpoint.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource privateEndpoint_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(privateEndpoint.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: privateEndpoint } - scope: privateEndpoint -}] +] @description('The resource group the private endpoint was deployed into.') output resourceGroupName string = resourceGroup().name @@ -142,7 +176,9 @@ output name string = privateEndpoint.name output location string = privateEndpoint.location @description('The group Id for the private endpoint Group.') -output groupId string = !empty(privateEndpoint.properties.manualPrivateLinkServiceConnections) ? privateEndpoint.properties.manualPrivateLinkServiceConnections[0].properties.groupIds[0] : privateEndpoint.properties.privateLinkServiceConnections[0].properties.groupIds[0] +output groupId string = !empty(privateEndpoint.properties.manualPrivateLinkServiceConnections) + ? privateEndpoint.properties.manualPrivateLinkServiceConnections[0].properties.groupIds[0] + : privateEndpoint.properties.privateLinkServiceConnections[0].properties.groupIds[0] // ================ // // Definitions // diff --git a/avm/res/network/private-endpoint/main.json b/avm/res/network/private-endpoint/main.json index b17d43e13f..3dd768bd4c 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.25.53.49325", - "templateHash": "8700281441025836130" + "version": "0.26.54.24096", + "templateHash": "2264842680766745282" }, "name": "Private Endpoints", "description": "This module deploys a Private Endpoint.", @@ -476,8 +476,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11244630631275470040" + "version": "0.26.54.24096", + "templateHash": "13696906123248879101" }, "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/private-dns-zone-group/main.bicep b/avm/res/network/private-endpoint/private-dns-zone-group/main.bicep index 623a713cbc..701f48a69c 100644 --- a/avm/res/network/private-endpoint/private-dns-zone-group/main.bicep +++ b/avm/res/network/private-endpoint/private-dns-zone-group/main.bicep @@ -13,12 +13,14 @@ param privateDNSResourceIds array @description('Optional. The name of the private DNS zone group.') param name string = 'default' -var privateDnsZoneConfigs = [for privateDNSResourceId in privateDNSResourceIds: { - name: last(split(privateDNSResourceId, '/'))! - properties: { - privateDnsZoneId: privateDNSResourceId +var privateDnsZoneConfigs = [ + for privateDNSResourceId in privateDNSResourceIds: { + name: last(split(privateDNSResourceId, '/'))! + properties: { + privateDnsZoneId: privateDNSResourceId + } } -}] +] resource privateEndpoint 'Microsoft.Network/privateEndpoints@2023-04-01' existing = { name: privateEndpointName 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 4428758907..3be73efbf6 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 @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11244630631275470040" + "version": "0.26.54.24096", + "templateHash": "13696906123248879101" }, "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 c133a0f4af..fb69ae8935 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 @@ -49,34 +49,36 @@ 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 - subnetResourceId: nestedDependencies.outputs.subnetResourceId - // Workaround for PSRule - lock: {} - roleAssignments: [] - applicationSecurityGroupResourceIds: [] - customNetworkInterfaceName: '' - privateDnsZoneGroupName: '' - ipConfigurations: [] - customDnsConfigs: [] - privateDnsZoneResourceIds: [] - manualPrivateLinkServiceConnections: [] - privateLinkServiceConnections: [ - { - name: '${namePrefix}${serviceShort}001' - properties: { - privateLinkServiceId: nestedDependencies.outputs.keyVaultResourceId - groupIds: [ - 'vault' - ] +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 + subnetResourceId: nestedDependencies.outputs.subnetResourceId + // Workaround for PSRule + lock: {} + roleAssignments: [] + applicationSecurityGroupResourceIds: [] + customNetworkInterfaceName: '' + privateDnsZoneGroupName: '' + ipConfigurations: [] + customDnsConfigs: [] + privateDnsZoneResourceIds: [] + manualPrivateLinkServiceConnections: [] + privateLinkServiceConnections: [ + { + name: '${namePrefix}${serviceShort}001' + properties: { + privateLinkServiceId: nestedDependencies.outputs.keyVaultResourceId + groupIds: [ + 'vault' + ] + } } - } - ] - tags: {} + ] + tags: {} + } } -}] +] 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 50cb5f95c7..22845ca801 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 @@ -51,78 +51,83 @@ 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 - subnetResourceId: nestedDependencies.outputs.subnetResourceId - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +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 + subnetResourceId: nestedDependencies.outputs.subnetResourceId + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - 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' - } - ] - ipConfigurations: [ - { - name: 'myIPconfig' - properties: { - groupId: 'vault' - memberName: 'default' - privateIPAddress: '10.0.0.10' + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + roleAssignments: [ + { + roleDefinitionIdOrName: 'Owner' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' } - } - ] - customDnsConfigs: [ - { - fqdn: 'abc.keyvault.com' - ipAddresses: [ - '10.0.0.10' - ] - } - ] - customNetworkInterfaceName: '${namePrefix}${serviceShort}001nic' - applicationSecurityGroupResourceIds: [ - nestedDependencies.outputs.applicationSecurityGroupResourceId - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - // Workaround for PSRule - privateDnsZoneGroupName: 'default' - manualPrivateLinkServiceConnections: [] - privateLinkServiceConnections: [ - { - name: '${namePrefix}${serviceShort}001' - properties: { - privateLinkServiceId: nestedDependencies.outputs.keyVaultResourceId - groupIds: [ - 'vault' + { + 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' + } + ] + ipConfigurations: [ + { + name: 'myIPconfig' + properties: { + groupId: 'vault' + memberName: 'default' + privateIPAddress: '10.0.0.10' + } + } + ] + customDnsConfigs: [ + { + fqdn: 'abc.keyvault.com' + ipAddresses: [ + '10.0.0.10' ] - requestMessage: 'Hey there' } + ] + customNetworkInterfaceName: '${namePrefix}${serviceShort}001nic' + applicationSecurityGroupResourceIds: [ + nestedDependencies.outputs.applicationSecurityGroupResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] + // Workaround for PSRule + privateDnsZoneGroupName: 'default' + manualPrivateLinkServiceConnections: [] + privateLinkServiceConnections: [ + { + name: '${namePrefix}${serviceShort}001' + properties: { + privateLinkServiceId: nestedDependencies.outputs.keyVaultResourceId + groupIds: [ + 'vault' + ] + requestMessage: 'Hey there' + } + } + ] + } } -}] +] 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 961dfd7d64..f90eb6358f 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 @@ -51,53 +51,55 @@ 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 - subnetResourceId: nestedDependencies.outputs.subnetResourceId - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - ipConfigurations: [ - { - name: 'myIPconfig' - properties: { - groupId: 'vault' - memberName: 'default' - privateIPAddress: '10.0.0.10' - } +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 + subnetResourceId: nestedDependencies.outputs.subnetResourceId + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - customNetworkInterfaceName: '${namePrefix}${serviceShort}001nic' - applicationSecurityGroupResourceIds: [ - nestedDependencies.outputs.applicationSecurityGroupResourceId - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - // Workaround for PSRule - privateDnsZoneGroupName: 'default' - customDnsConfigs: [] - manualPrivateLinkServiceConnections: [] - privateLinkServiceConnections: [ - { - name: '${namePrefix}${serviceShort}001' - properties: { - privateLinkServiceId: nestedDependencies.outputs.keyVaultResourceId - groupIds: [ - 'vault' - ] + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + ipConfigurations: [ + { + name: 'myIPconfig' + properties: { + groupId: 'vault' + memberName: 'default' + privateIPAddress: '10.0.0.10' + } } + ] + customNetworkInterfaceName: '${namePrefix}${serviceShort}001nic' + applicationSecurityGroupResourceIds: [ + nestedDependencies.outputs.applicationSecurityGroupResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] + // Workaround for PSRule + privateDnsZoneGroupName: 'default' + customDnsConfigs: [] + manualPrivateLinkServiceConnections: [] + privateLinkServiceConnections: [ + { + name: '${namePrefix}${serviceShort}001' + properties: { + privateLinkServiceId: nestedDependencies.outputs.keyVaultResourceId + groupIds: [ + 'vault' + ] + } + } + ] + } } -}] +] diff --git a/avm/res/network/private-link-service/main.bicep b/avm/res/network/private-link-service/main.bicep index edf06dc31b..3b2e4fe0f8 100644 --- a/avm/res/network/private-link-service/main.bicep +++ b/avm/res/network/private-link-service/main.bicep @@ -43,31 +43,44 @@ param enableTelemetry bool = true var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + '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') + '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') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-privatelinkservice.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-privatelinkservice.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource privateLinkService 'Microsoft.Network/privateLinkServices@2023-04-01' = { name: name @@ -84,28 +97,37 @@ resource privateLinkService 'Microsoft.Network/privateLinkServices@2023-04-01' = } } -resource privateLinkService_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.' +resource privateLinkService_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: privateLinkService } - scope: privateLinkService -} -resource privateLinkService_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(privateLinkService.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource privateLinkService_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(privateLinkService.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: privateLinkService } - scope: privateLinkService -}] +] @description('The resource group the private link service was deployed into.') output resourceGroupName string = resourceGroup().name diff --git a/avm/res/network/private-link-service/main.json b/avm/res/network/private-link-service/main.json index 50f7678349..1b3d84fbfc 100644 --- a/avm/res/network/private-link-service/main.json +++ b/avm/res/network/private-link-service/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3313526188226682107" + "version": "0.26.54.24096", + "templateHash": "3016081933561782423" }, "name": "Private Link Services", "description": "This module deploys a Private Link Service.", diff --git a/avm/res/network/private-link-service/tests/e2e/defaults/main.test.bicep b/avm/res/network/private-link-service/tests/e2e/defaults/main.test.bicep index 225912bdc2..133ed317d1 100644 --- a/avm/res/network/private-link-service/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/private-link-service/tests/e2e/defaults/main.test.bicep @@ -46,26 +46,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 - ipConfigurations: [ - { - name: '${serviceShort}01' - properties: { - subnet: { - id: nestedDependencies.outputs.subnetResourceId +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 + ipConfigurations: [ + { + name: '${serviceShort}01' + properties: { + subnet: { + id: nestedDependencies.outputs.subnetResourceId + } } } - } - ] - loadBalancerFrontendIpConfigurations: [ - { - id: nestedDependencies.outputs.loadBalancerFrontendIpConfigurationResourceId - } - ] + ] + loadBalancerFrontendIpConfigurations: [ + { + id: nestedDependencies.outputs.loadBalancerFrontendIpConfigurationResourceId + } + ] + } } -}] +] diff --git a/avm/res/network/private-link-service/tests/e2e/max/main.test.bicep b/avm/res/network/private-link-service/tests/e2e/max/main.test.bicep index 8fd89f8691..1efed5c5a3 100644 --- a/avm/res/network/private-link-service/tests/e2e/max/main.test.bicep +++ b/avm/res/network/private-link-service/tests/e2e/max/main.test.bicep @@ -47,69 +47,74 @@ 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 - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - ipConfigurations: [ - { - name: '${serviceShort}01' - properties: { - primary: true - privateIPAllocationMethod: 'Dynamic' - subnet: { - id: nestedDependencies.outputs.subnetResourceId +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 + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + ipConfigurations: [ + { + name: '${serviceShort}01' + properties: { + primary: true + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: nestedDependencies.outputs.subnetResourceId + } } } - } - ] - loadBalancerFrontendIpConfigurations: [ - { - id: nestedDependencies.outputs.loadBalancerFrontendIpConfigurationResourceId - } - ] - autoApproval: { - subscriptions: [ - '*' ] - } - visibility: { - subscriptions: [ - subscription().subscriptionId + loadBalancerFrontendIpConfigurations: [ + { + id: nestedDependencies.outputs.loadBalancerFrontendIpConfigurationResourceId + } ] - } - enableProxyProtocol: true - fqdns: [ - '${serviceShort}.plsfqdn01.azure.privatelinkservice' - '${serviceShort}.plsfqdn02.azure.privatelinkservice' - ] - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + autoApproval: { + subscriptions: [ + '*' + ] } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + visibility: { + subscriptions: [ + subscription().subscriptionId + ] } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + enableProxyProtocol: true + fqdns: [ + '${serviceShort}.plsfqdn01.azure.privatelinkservice' + '${serviceShort}.plsfqdn02.azure.privatelinkservice' + ] + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/network/private-link-service/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/private-link-service/tests/e2e/waf-aligned/main.test.bicep index 1c3944a326..48b68e42be 100644 --- a/avm/res/network/private-link-service/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/private-link-service/tests/e2e/waf-aligned/main.test.bicep @@ -46,48 +46,50 @@ 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 - ipConfigurations: [ - { - name: '${serviceShort}01' - properties: { - primary: true - privateIPAllocationMethod: 'Dynamic' - subnet: { - id: nestedDependencies.outputs.subnetResourceId +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 + ipConfigurations: [ + { + name: '${serviceShort}01' + properties: { + primary: true + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: nestedDependencies.outputs.subnetResourceId + } } } + ] + loadBalancerFrontendIpConfigurations: [ + { + id: nestedDependencies.outputs.loadBalancerFrontendIpConfigurationResourceId + } + ] + autoApproval: { + subscriptions: [ + '*' + ] } - ] - loadBalancerFrontendIpConfigurations: [ - { - id: nestedDependencies.outputs.loadBalancerFrontendIpConfigurationResourceId + visibility: { + subscriptions: [ + subscription().subscriptionId + ] } - ] - autoApproval: { - subscriptions: [ - '*' - ] - } - visibility: { - subscriptions: [ - subscription().subscriptionId + enableProxyProtocol: true + fqdns: [ + '${serviceShort}.plsfqdn01.azure.privatelinkservice' + '${serviceShort}.plsfqdn02.azure.privatelinkservice' ] - } - enableProxyProtocol: true - fqdns: [ - '${serviceShort}.plsfqdn01.azure.privatelinkservice' - '${serviceShort}.plsfqdn02.azure.privatelinkservice' - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } } -}] +] diff --git a/avm/res/network/public-ip-address/main.bicep b/avm/res/network/public-ip-address/main.bicep index ef48ffb569..36c04b157f 100644 --- a/avm/res/network/public-ip-address/main.bicep +++ b/avm/res/network/public-ip-address/main.bicep @@ -72,34 +72,56 @@ param diagnosticSettings diagnosticSettingType var 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') + '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') + '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 (Preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-publicipaddress.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-publicipaddress.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource publicIpAddress 'Microsoft.Network/publicIPAddresses@2023-09-01' = { name: name @@ -115,59 +137,76 @@ resource publicIpAddress 'Microsoft.Network/publicIPAddresses@2023-09-01' = { dnsSettings: dnsSettings publicIPAddressVersion: publicIPAddressVersion publicIPAllocationMethod: publicIPAllocationMethod - publicIPPrefix: !empty(publicIpPrefixResourceId) ? { - id: publicIpPrefixResourceId - } : null + publicIPPrefix: !empty(publicIpPrefixResourceId) + ? { + id: publicIpPrefixResourceId + } + : null idleTimeoutInMinutes: idleTimeoutInMinutes ipTags: [] } } -resource publicIpAddress_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.' +resource publicIpAddress_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: publicIpAddress } - scope: publicIpAddress -} -resource publicIpAddress_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(publicIpAddress.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource publicIpAddress_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(publicIpAddress.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: publicIpAddress } - scope: publicIpAddress -}] +] -resource publicIpAddress_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource publicIpAddress_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: publicIpAddress } - scope: publicIpAddress -}] +] @description('The resource group the public IP address was deployed into.') output resourceGroupName string = resourceGroup().name diff --git a/avm/res/network/public-ip-address/tests/e2e/defaults/main.test.bicep b/avm/res/network/public-ip-address/tests/e2e/defaults/main.test.bicep index 8aec5abcad..fa38cabbae 100644 --- a/avm/res/network/public-ip-address/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/public-ip-address/tests/e2e/defaults/main.test.bicep @@ -35,11 +35,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // Test Execution // // ============== // -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 +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 + } } -}] +] 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 11e3670a5e..9c75dd5ace 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 @@ -58,58 +58,63 @@ module diagnosticDependencies '../../../../../../../avm/utilities/e2e-template-a // Test Execution // // ============== // -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 - lock: { - name: 'myCustomLockName' - kind: 'CanNotDelete' - } - dnsSettings: null - ddosSettings: null - publicIpPrefixResourceId: null - publicIPAllocationMethod: 'Static' - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +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 + lock: { + name: 'myCustomLockName' + kind: 'CanNotDelete' } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + dnsSettings: null + ddosSettings: null + publicIpPrefixResourceId: null + publicIPAllocationMethod: 'Static' + 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' + } + ] + skuName: 'Standard' + skuTier: 'Regional' + publicIPAddressVersion: 'IPv4' + zones: [ + '1' + '2' + '3' + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - skuName: 'Standard' - skuTier: 'Regional' - publicIPAddressVersion: 'IPv4' - zones: [ - '1' - '2' - '3' - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + diagnosticSettings: [ + { + name: 'customSetting' + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] } - diagnosticSettings: [ - { - name: 'customSetting' - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] } -}] +] diff --git a/avm/res/network/public-ip-address/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/public-ip-address/tests/e2e/waf-aligned/main.test.bicep index ebf0000da7..0a7930b56e 100644 --- a/avm/res/network/public-ip-address/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/public-ip-address/tests/e2e/waf-aligned/main.test.bicep @@ -58,58 +58,63 @@ module diagnosticDependencies '../../../../../../../avm/utilities/e2e-template-a // Test Execution // // ============== // -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 - lock: { - name: 'myCustomLockName' - kind: 'CanNotDelete' - } - dnsSettings: null - ddosSettings: null - publicIPAllocationMethod: 'Static' - publicIpPrefixResourceId: null - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +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 + lock: { + name: 'myCustomLockName' + kind: 'CanNotDelete' } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + dnsSettings: null + ddosSettings: null + publicIPAllocationMethod: 'Static' + publicIpPrefixResourceId: null + 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' + } + ] + skuName: 'Standard' + skuTier: 'Regional' + publicIPAddressVersion: 'IPv4' + zones: [ + '1' + '2' + '3' + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - skuName: 'Standard' - skuTier: 'Regional' - publicIPAddressVersion: 'IPv4' - zones: [ - '1' - '2' - '3' - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + diagnosticSettings: [ + { + name: 'customSetting' + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] } - diagnosticSettings: [ - { - name: 'customSetting' - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] } -}] +] diff --git a/avm/res/network/public-ip-prefix/main.bicep b/avm/res/network/public-ip-prefix/main.bicep index d9fed7fb9d..91383b47dc 100644 --- a/avm/res/network/public-ip-prefix/main.bicep +++ b/avm/res/network/public-ip-prefix/main.bicep @@ -31,30 +31,40 @@ param enableTelemetry bool = true var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + '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') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-publicipprefix.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-publicipprefix.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource publicIpPrefix 'Microsoft.Network/publicIPPrefixes@2023-09-01' = { name: name @@ -70,28 +80,37 @@ resource publicIpPrefix 'Microsoft.Network/publicIPPrefixes@2023-09-01' = { } } -resource publicIpPrefix_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.' +resource publicIpPrefix_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: publicIpPrefix } - scope: publicIpPrefix -} -resource publicIpPrefix_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(publicIpPrefix.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource publicIpPrefix_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(publicIpPrefix.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: publicIpPrefix } - scope: publicIpPrefix -}] +] @description('The resource ID of the public IP prefix.') output resourceId string = publicIpPrefix.id diff --git a/avm/res/network/public-ip-prefix/main.json b/avm/res/network/public-ip-prefix/main.json index bf928ff5b7..4e2479e6a3 100644 --- a/avm/res/network/public-ip-prefix/main.json +++ b/avm/res/network/public-ip-prefix/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16912543771400413342" + "version": "0.26.54.24096", + "templateHash": "7016457133056549138" }, "name": "Public IP Prefixes", "description": "This module deploys a Public IP Prefix.", 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 70effcbbc5..271d5ed8ee 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 @@ -35,12 +35,14 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2023-07-01' = { // ============== // @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: 28 +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: 28 + } } -}] +] diff --git a/avm/res/network/public-ip-prefix/tests/e2e/max/dependencies.bicep b/avm/res/network/public-ip-prefix/tests/e2e/max/dependencies.bicep index 43b2b39c33..7b3d4e8fb0 100644 --- a/avm/res/network/public-ip-prefix/tests/e2e/max/dependencies.bicep +++ b/avm/res/network/public-ip-prefix/tests/e2e/max/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') 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 6504f4b21b..c4e9682513 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 @@ -45,38 +45,43 @@ 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 - prefixLength: 28 - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +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: 28 + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/network/public-ip-prefix/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/network/public-ip-prefix/tests/e2e/waf-aligned/dependencies.bicep index 43b2b39c33..7b3d4e8fb0 100644 --- a/avm/res/network/public-ip-prefix/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/network/public-ip-prefix/tests/e2e/waf-aligned/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') 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 6e2ba0e646..469fe72abf 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 @@ -36,17 +36,19 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2023-07-01' = { // ============== // @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: 28 - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +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: 28 + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } } -}] +] diff --git a/avm/res/network/route-table/main.bicep b/avm/res/network/route-table/main.bicep index e5dcc4f652..c26a3d25d1 100644 --- a/avm/res/network/route-table/main.bicep +++ b/avm/res/network/route-table/main.bicep @@ -28,30 +28,43 @@ param enableTelemetry bool = true var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + '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') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: take('46d3xbcp.res.network-routetable.${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' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: take( + '46d3xbcp.res.network-routetable.${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' + } } } } } -} resource routeTable 'Microsoft.Network/routeTables@2023-04-01' = { name: name @@ -63,28 +76,37 @@ resource routeTable 'Microsoft.Network/routeTables@2023-04-01' = { } } -resource routeTable_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.' +resource routeTable_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: routeTable } - scope: routeTable -} -resource routeTable_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(routeTable.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource routeTable_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(routeTable.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: routeTable } - scope: routeTable -}] +] @description('The resource group the route table was deployed into.') output resourceGroupName string = resourceGroup().name diff --git a/avm/res/network/route-table/main.json b/avm/res/network/route-table/main.json index 3f54614e78..e0818709a4 100644 --- a/avm/res/network/route-table/main.json +++ b/avm/res/network/route-table/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "1632746009017446160" + "version": "0.26.54.24096", + "templateHash": "3951814789593298488" }, "name": "Route Tables", "description": "This module deploys a User Defined Route Table (UDR).", diff --git a/avm/res/network/route-table/tests/e2e/max/dependencies.bicep b/avm/res/network/route-table/tests/e2e/max/dependencies.bicep index a7f42aee7b..7be39e253a 100644 --- a/avm/res/network/route-table/tests/e2e/max/dependencies.bicep +++ b/avm/res/network/route-table/tests/e2e/max/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/network/route-table/tests/e2e/max/main.test.bicep b/avm/res/network/route-table/tests/e2e/max/main.test.bicep index 82c3e2627b..52bcc02ac8 100644 --- a/avm/res/network/route-table/tests/e2e/max/main.test.bicep +++ b/avm/res/network/route-table/tests/e2e/max/main.test.bicep @@ -66,7 +66,10 @@ module testDeployment '../../../main.bicep' = { principalType: 'ServicePrincipal' } { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) principalId: nestedDependencies.outputs.managedIdentityPrincipalId principalType: 'ServicePrincipal' } diff --git a/avm/res/network/trafficmanagerprofile/main.bicep b/avm/res/network/trafficmanagerprofile/main.bicep index fadcb2ff94..77a4f05dad 100644 --- a/avm/res/network/trafficmanagerprofile/main.bicep +++ b/avm/res/network/trafficmanagerprofile/main.bicep @@ -70,31 +70,44 @@ param location string = 'global' var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + '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') - 'Traffic Manager Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4b10055-b0c7-44c2-b00f-c7b5b3550cf7') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' + ) + 'Traffic Manager Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'a4b10055-b0c7-44c2-b00f-c7b5b3550cf7' + ) + 'User Access Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-trafficmanagerprofile.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-trafficmanagerprofile.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource trafficManagerProfile 'Microsoft.Network/trafficmanagerprofiles@2018-08-01' = { name: name @@ -114,51 +127,66 @@ resource trafficManagerProfile 'Microsoft.Network/trafficmanagerprofiles@2018-08 } } -resource trafficManagerProfile_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.' +resource trafficManagerProfile_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: trafficManagerProfile } - scope: trafficManagerProfile -} -resource trafficManagerProfile_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource trafficManagerProfile_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: trafficManagerProfile } - scope: trafficManagerProfile -}] - -resource trafficManagerProfile_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(trafficManagerProfile.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +] + +resource trafficManagerProfile_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(trafficManagerProfile.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: trafficManagerProfile } - scope: trafficManagerProfile -}] +] @description('The resource ID of the traffic manager.') output resourceId string = trafficManagerProfile.id diff --git a/avm/res/network/trafficmanagerprofile/main.json b/avm/res/network/trafficmanagerprofile/main.json index 5eb1678de9..8c4e575316 100644 --- a/avm/res/network/trafficmanagerprofile/main.json +++ b/avm/res/network/trafficmanagerprofile/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "1216778685608382825" + "version": "0.26.54.24096", + "templateHash": "7725817516330218838" }, "name": "Traffic Manager Profiles", "description": "This module deploys a Traffic Manager Profile.", diff --git a/avm/res/network/trafficmanagerprofile/tests/e2e/defaults/main.test.bicep b/avm/res/network/trafficmanagerprofile/tests/e2e/defaults/main.test.bicep index 1f0aca0761..821e67a2cc 100644 --- a/avm/res/network/trafficmanagerprofile/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/trafficmanagerprofile/tests/e2e/defaults/main.test.bicep @@ -35,11 +35,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // 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: 'global' +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: 'global' + } } -}] +] diff --git a/avm/res/network/trafficmanagerprofile/tests/e2e/max/main.test.bicep b/avm/res/network/trafficmanagerprofile/tests/e2e/max/main.test.bicep index b42bac759e..b756d168b8 100644 --- a/avm/res/network/trafficmanagerprofile/tests/e2e/max/main.test.bicep +++ b/avm/res/network/trafficmanagerprofile/tests/e2e/max/main.test.bicep @@ -58,52 +58,57 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t // 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' - relativeName: '${namePrefix}${serviceShort}001-rn' - location: 'global' - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + relativeName: '${namePrefix}${serviceShort}001-rn' + location: 'global' + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/network/trafficmanagerprofile/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/trafficmanagerprofile/tests/e2e/waf-aligned/main.test.bicep index cb2cc08da1..32d82ac36b 100644 --- a/avm/res/network/trafficmanagerprofile/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/trafficmanagerprofile/tests/e2e/waf-aligned/main.test.bicep @@ -64,63 +64,65 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t // 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: 'global' - monitorConfig: { - protocol: 'https' - port: '443' - path: '/' - } - 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: 'global' + monitorConfig: { + protocol: 'https' + port: '443' + path: '/' } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - endpoints: [ - { - name: 'webApp01Endpoint' - type: 'Microsoft.Network/trafficManagerProfiles/azureEndpoints' - properties: { - targetResourceId: nestedDependencies.outputs.webApp01ResourceId - weight: 1 - priority: 1 - endpointLocation: 'eastus' - endpointStatus: 'Enabled' + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - name: 'webApp02Endpoint' - type: 'Microsoft.Network/trafficManagerProfiles/azureEndpoints' - properties: { - targetResourceId: nestedDependencies.outputs.webApp02ResourceId - weight: 1 - priority: 2 - endpointLocation: 'westus' - endpointStatus: 'Enabled' - } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] + endpoints: [ + { + name: 'webApp01Endpoint' + type: 'Microsoft.Network/trafficManagerProfiles/azureEndpoints' + properties: { + targetResourceId: nestedDependencies.outputs.webApp01ResourceId + weight: 1 + priority: 1 + endpointLocation: 'eastus' + endpointStatus: 'Enabled' + } + } + { + name: 'webApp02Endpoint' + type: 'Microsoft.Network/trafficManagerProfiles/azureEndpoints' + properties: { + targetResourceId: nestedDependencies.outputs.webApp02ResourceId + weight: 1 + priority: 2 + endpointLocation: 'westus' + endpointStatus: 'Enabled' + } + } + ] + } } -}] +] diff --git a/avm/res/network/virtual-hub/hub-route-table/main.bicep b/avm/res/network/virtual-hub/hub-route-table/main.bicep index 46d6d2d895..059374a501 100644 --- a/avm/res/network/virtual-hub/hub-route-table/main.bicep +++ b/avm/res/network/virtual-hub/hub-route-table/main.bicep @@ -17,23 +17,24 @@ param routes array = [] @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-virtualhub.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name), 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' +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-virtualhub.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name), 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' + } } } } } -} resource virtualHub 'Microsoft.Network/virtualHubs@2022-11-01' existing = { name: virtualHubName diff --git a/avm/res/network/virtual-hub/hub-route-table/main.json b/avm/res/network/virtual-hub/hub-route-table/main.json index 200e6c44d7..0188d1b4bc 100644 --- a/avm/res/network/virtual-hub/hub-route-table/main.json +++ b/avm/res/network/virtual-hub/hub-route-table/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "10525202939204553685" + "version": "0.26.54.24096", + "templateHash": "8788910381196616673" }, "name": "Virtual Hub Route Tables", "description": "This module deploys a Virtual Hub Route Table.", diff --git a/avm/res/network/virtual-hub/hub-virtual-network-connection/main.bicep b/avm/res/network/virtual-hub/hub-virtual-network-connection/main.bicep index 6e0c0c3119..3bc4c7e4ec 100644 --- a/avm/res/network/virtual-hub/hub-virtual-network-connection/main.bicep +++ b/avm/res/network/virtual-hub/hub-virtual-network-connection/main.bicep @@ -20,23 +20,24 @@ param routingConfiguration object = {} @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-virtualhub.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name), 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' +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-virtualhub.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name), 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' + } } } } } -} resource virtualHub 'Microsoft.Network/virtualHubs@2022-11-01' existing = { name: virtualHubName diff --git a/avm/res/network/virtual-hub/hub-virtual-network-connection/main.json b/avm/res/network/virtual-hub/hub-virtual-network-connection/main.json index ea8e5a326f..47c9ebd025 100644 --- a/avm/res/network/virtual-hub/hub-virtual-network-connection/main.json +++ b/avm/res/network/virtual-hub/hub-virtual-network-connection/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2449431200083704591" + "version": "0.26.54.24096", + "templateHash": "10987823499253979342" }, "name": "Virtual Hub Virtual Network Connections", "description": "This module deploys a Virtual Hub Virtual Network Connection.", diff --git a/avm/res/network/virtual-hub/main.bicep b/avm/res/network/virtual-hub/main.bicep index e6326c72bf..58c7ad44d2 100644 --- a/avm/res/network/virtual-hub/main.bicep +++ b/avm/res/network/virtual-hub/main.bicep @@ -81,23 +81,27 @@ param enableTelemetry bool = true var enableReferencedModulesTelemetry = false -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: take('46d3xbcp.res.network-virtualhub.${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' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: take( + '46d3xbcp.res.network-virtualhub.${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' + } } } } } -} resource virtualHub 'Microsoft.Network/virtualHubs@2022-11-01' = { name: name @@ -106,22 +110,32 @@ resource virtualHub 'Microsoft.Network/virtualHubs@2022-11-01' = { properties: { addressPrefix: addressPrefix allowBranchToBranchTraffic: allowBranchToBranchTraffic - azureFirewall: !empty(azureFirewallResourceId) ? { - id: azureFirewallResourceId - } : null - expressRouteGateway: !empty(expressRouteGatewayId) ? { - id: expressRouteGatewayId - } : null - p2SVpnGateway: !empty(p2SVpnGatewayId) ? { - id: p2SVpnGatewayId - } : null + azureFirewall: !empty(azureFirewallResourceId) + ? { + id: azureFirewallResourceId + } + : null + expressRouteGateway: !empty(expressRouteGatewayId) + ? { + id: expressRouteGatewayId + } + : null + p2SVpnGateway: !empty(p2SVpnGatewayId) + ? { + id: p2SVpnGatewayId + } + : null preferredRoutingGateway: !empty(preferredRoutingGateway) ? any(preferredRoutingGateway) : null - routeTable: !empty(routeTableRoutes) ? { - routes: routeTableRoutes - } : null - securityPartnerProvider: !empty(securityPartnerProviderId) ? { - id: securityPartnerProviderId - } : null + routeTable: !empty(routeTableRoutes) + ? { + routes: routeTableRoutes + } + : null + securityPartnerProvider: !empty(securityPartnerProviderId) + ? { + id: securityPartnerProviderId + } + : null securityProviderName: securityProviderName sku: sku virtualHubRouteTableV2s: virtualHubRouteTableV2s @@ -130,46 +144,59 @@ resource virtualHub 'Microsoft.Network/virtualHubs@2022-11-01' = { virtualWan: { id: virtualWanId } - vpnGateway: !empty(vpnGatewayId) ? { - id: vpnGatewayId - } : null + vpnGateway: !empty(vpnGatewayId) + ? { + id: vpnGatewayId + } + : null } } -resource virtualHub_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.' +resource virtualHub_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: virtualHub } - scope: virtualHub -} -module virtualHub_routeTables 'hub-route-table/main.bicep' = [for (routeTable, index) in hubRouteTables: { - name: '${uniqueString(deployment().name, location)}-routeTable-${index}' - params: { - virtualHubName: virtualHub.name - name: routeTable.name - labels: contains(routeTable, 'labels') ? routeTable.labels : [] - routes: contains(routeTable, 'routes') ? routeTable.routes : [] - enableTelemetry: enableReferencedModulesTelemetry +module virtualHub_routeTables 'hub-route-table/main.bicep' = [ + for (routeTable, index) in hubRouteTables: { + name: '${uniqueString(deployment().name, location)}-routeTable-${index}' + params: { + virtualHubName: virtualHub.name + name: routeTable.name + labels: contains(routeTable, 'labels') ? routeTable.labels : [] + routes: contains(routeTable, 'routes') ? routeTable.routes : [] + enableTelemetry: enableReferencedModulesTelemetry + } } -}] - -module virtualHub_hubVirtualNetworkConnections 'hub-virtual-network-connection/main.bicep' = [for (virtualNetworkConnection, index) in hubVirtualNetworkConnections: { - name: '${uniqueString(deployment().name, location)}-connection-${index}' - params: { - virtualHubName: virtualHub.name - name: virtualNetworkConnection.name - enableInternetSecurity: contains(virtualNetworkConnection, 'enableInternetSecurity') ? virtualNetworkConnection.enableInternetSecurity : true - remoteVirtualNetworkId: virtualNetworkConnection.remoteVirtualNetworkId - routingConfiguration: contains(virtualNetworkConnection, 'routingConfiguration') ? virtualNetworkConnection.routingConfiguration : {} - enableTelemetry: enableReferencedModulesTelemetry +] + +module virtualHub_hubVirtualNetworkConnections 'hub-virtual-network-connection/main.bicep' = [ + for (virtualNetworkConnection, index) in hubVirtualNetworkConnections: { + name: '${uniqueString(deployment().name, location)}-connection-${index}' + params: { + virtualHubName: virtualHub.name + name: virtualNetworkConnection.name + enableInternetSecurity: contains(virtualNetworkConnection, 'enableInternetSecurity') + ? virtualNetworkConnection.enableInternetSecurity + : true + remoteVirtualNetworkId: virtualNetworkConnection.remoteVirtualNetworkId + routingConfiguration: contains(virtualNetworkConnection, 'routingConfiguration') + ? virtualNetworkConnection.routingConfiguration + : {} + enableTelemetry: enableReferencedModulesTelemetry + } + dependsOn: [ + virtualHub_routeTables + ] } - dependsOn: [ - virtualHub_routeTables - ] -}] +] @description('The resource group the virtual hub was deployed into.') output resourceGroupName string = resourceGroup().name diff --git a/avm/res/network/virtual-hub/main.json b/avm/res/network/virtual-hub/main.json index b230823993..5b75ef5cc5 100644 --- a/avm/res/network/virtual-hub/main.json +++ b/avm/res/network/virtual-hub/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14890345402999745367" + "version": "0.26.54.24096", + "templateHash": "2150058177195720553" }, "name": "Virtual Hubs", "description": "This module deploys a Virtual Hub.\nIf you are planning to deploy a Secure Virtual Hub (with an Azure Firewall integrated), please refer to the Azure Firewall module.", @@ -297,8 +297,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "10525202939204553685" + "version": "0.26.54.24096", + "templateHash": "8788910381196616673" }, "name": "Virtual Hub Route Tables", "description": "This module deploys a Virtual Hub Route Table.", @@ -434,8 +434,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2449431200083704591" + "version": "0.26.54.24096", + "templateHash": "10987823499253979342" }, "name": "Virtual Hub Virtual Network Connections", "description": "This module deploys a Virtual Hub Virtual Network Connection.", diff --git a/avm/res/network/virtual-hub/tests/e2e/defaults/main.test.bicep b/avm/res/network/virtual-hub/tests/e2e/defaults/main.test.bicep index 5f6bfff780..688058b279 100644 --- a/avm/res/network/virtual-hub/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/virtual-hub/tests/e2e/defaults/main.test.bicep @@ -17,7 +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 = 'nvhmin' - @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' @@ -46,13 +45,15 @@ 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}' - addressPrefix: '10.0.0.0/16' - virtualWanId: nestedDependencies.outputs.virtualWWANResourceId - location: resourceLocation +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}-${serviceShort}' + addressPrefix: '10.0.0.0/16' + virtualWanId: nestedDependencies.outputs.virtualWWANResourceId + location: resourceLocation + } } -}] +] diff --git a/avm/res/network/virtual-hub/tests/e2e/max/dependencies.bicep b/avm/res/network/virtual-hub/tests/e2e/max/dependencies.bicep index 9c4af5313d..12d02b46c1 100644 --- a/avm/res/network/virtual-hub/tests/e2e/max/dependencies.bicep +++ b/avm/res/network/virtual-hub/tests/e2e/max/dependencies.bicep @@ -27,7 +27,6 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { { name: 'defaultSubnet' properties: { - addressPrefix: cidrSubnet(addressPrefix, 16, 0) } } diff --git a/avm/res/network/virtual-hub/tests/e2e/max/main.test.bicep b/avm/res/network/virtual-hub/tests/e2e/max/main.test.bicep index 0e72b20ad4..5b1d77520f 100644 --- a/avm/res/network/virtual-hub/tests/e2e/max/main.test.bicep +++ b/avm/res/network/virtual-hub/tests/e2e/max/main.test.bicep @@ -46,48 +46,50 @@ 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: { - location: resourceLocation - name: '${namePrefix}-${serviceShort}' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - addressPrefix: '10.1.0.0/16' - virtualWanId: nestedDependencies.outputs.virtualWWANResourceId - hubRouteTables: [ - { - name: 'routeTable1' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}-${serviceShort}' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - hubVirtualNetworkConnections: [ - { - name: 'connection1' - remoteVirtualNetworkId: nestedDependencies.outputs.virtualNetworkResourceId - routingConfiguration: { - associatedRouteTable: { - id: '${resourceGroup.id}/providers/Microsoft.Network/virtualHubs/${namePrefix}-${serviceShort}/hubRouteTables/routeTable1' - } - propagatedRouteTables: { - ids: [ - { - id: '${resourceGroup.id}/providers/Microsoft.Network/virtualHubs/${namePrefix}-${serviceShort}/hubRouteTables/routeTable1' - } - ] - labels: [ - 'none' - ] + addressPrefix: '10.1.0.0/16' + virtualWanId: nestedDependencies.outputs.virtualWWANResourceId + hubRouteTables: [ + { + name: 'routeTable1' + } + ] + hubVirtualNetworkConnections: [ + { + name: 'connection1' + remoteVirtualNetworkId: nestedDependencies.outputs.virtualNetworkResourceId + routingConfiguration: { + associatedRouteTable: { + id: '${resourceGroup.id}/providers/Microsoft.Network/virtualHubs/${namePrefix}-${serviceShort}/hubRouteTables/routeTable1' + } + propagatedRouteTables: { + ids: [ + { + id: '${resourceGroup.id}/providers/Microsoft.Network/virtualHubs/${namePrefix}-${serviceShort}/hubRouteTables/routeTable1' + } + ] + labels: [ + 'none' + ] + } } } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/network/virtual-hub/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/network/virtual-hub/tests/e2e/waf-aligned/dependencies.bicep index 9c4af5313d..12d02b46c1 100644 --- a/avm/res/network/virtual-hub/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/network/virtual-hub/tests/e2e/waf-aligned/dependencies.bicep @@ -27,7 +27,6 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { { name: 'defaultSubnet' properties: { - addressPrefix: cidrSubnet(addressPrefix, 16, 0) } } diff --git a/avm/res/network/virtual-hub/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/virtual-hub/tests/e2e/waf-aligned/main.test.bicep index ee601164eb..3d3015b25f 100644 --- a/avm/res/network/virtual-hub/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/virtual-hub/tests/e2e/waf-aligned/main.test.bicep @@ -46,48 +46,50 @@ 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}' - location: resourceLocation - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - addressPrefix: '10.1.0.0/16' - virtualWanId: nestedDependencies.outputs.virtualWWANResourceId - hubRouteTables: [ - { - name: 'routeTable1' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}-${serviceShort}' + location: resourceLocation + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - hubVirtualNetworkConnections: [ - { - name: 'connection1' - remoteVirtualNetworkId: nestedDependencies.outputs.virtualNetworkResourceId - routingConfiguration: { - associatedRouteTable: { - id: '${resourceGroup.id}/providers/Microsoft.Network/virtualHubs/${namePrefix}-${serviceShort}/hubRouteTables/routeTable1' - } - propagatedRouteTables: { - ids: [ - { - id: '${resourceGroup.id}/providers/Microsoft.Network/virtualHubs/${namePrefix}-${serviceShort}/hubRouteTables/routeTable1' - } - ] - labels: [ - 'none' - ] + addressPrefix: '10.1.0.0/16' + virtualWanId: nestedDependencies.outputs.virtualWWANResourceId + hubRouteTables: [ + { + name: 'routeTable1' + } + ] + hubVirtualNetworkConnections: [ + { + name: 'connection1' + remoteVirtualNetworkId: nestedDependencies.outputs.virtualNetworkResourceId + routingConfiguration: { + associatedRouteTable: { + id: '${resourceGroup.id}/providers/Microsoft.Network/virtualHubs/${namePrefix}-${serviceShort}/hubRouteTables/routeTable1' + } + propagatedRouteTables: { + ids: [ + { + id: '${resourceGroup.id}/providers/Microsoft.Network/virtualHubs/${namePrefix}-${serviceShort}/hubRouteTables/routeTable1' + } + ] + labels: [ + 'none' + ] + } } } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/network/virtual-network-gateway/main.bicep b/avm/res/network/virtual-network-gateway/main.bicep index 1057d03afd..b27289ffa6 100644 --- a/avm/res/network/virtual-network-gateway/main.bicep +++ b/avm/res/network/virtual-network-gateway/main.bicep @@ -152,12 +152,14 @@ var gatewayPipSku = contains(zoneRedundantSkus, skuName) ? 'Standard' : 'Basic' var gatewayPipAllocationMethod = contains(zoneRedundantSkus, skuName) ? 'Static' : 'Dynamic' var isActiveActiveValid = gatewayType != 'ExpressRoute' ? activeActive : false -var virtualGatewayPipNameVar = isActiveActiveValid ? [ - gatewayPipName - activeGatewayPipName -] : [ - gatewayPipName -] +var virtualGatewayPipNameVar = isActiveActiveValid + ? [ + gatewayPipName + activeGatewayPipName + ] + : [ + gatewayPipName + ] var vpnTypeVar = gatewayType != 'ExpressRoute' ? vpnType : 'PolicyBased' @@ -167,132 +169,159 @@ var bgpSettings = { } // Potential configurations (active-active vs active-passive) -var ipConfiguration = isActiveActiveValid ? [ - { - properties: { - privateIPAllocationMethod: 'Dynamic' - subnet: { - id: '${vNetResourceId}/subnets/GatewaySubnet' - } - publicIPAddress: { - id: az.resourceId('Microsoft.Network/publicIPAddresses', gatewayPipName) - } - } - name: 'vNetGatewayConfig1' - } - { - properties: { - privateIPAllocationMethod: 'Dynamic' - subnet: { - id: '${vNetResourceId}/subnets/GatewaySubnet' - } - publicIPAddress: { - id: isActiveActiveValid ? az.resourceId('Microsoft.Network/publicIPAddresses', activeGatewayPipName) : az.resourceId('Microsoft.Network/publicIPAddresses', gatewayPipName) - } - } - name: 'vNetGatewayConfig2' - } -] : [ - { - properties: { - privateIPAllocationMethod: 'Dynamic' - subnet: { - id: '${vNetResourceId}/subnets/GatewaySubnet' +var ipConfiguration = isActiveActiveValid + ? [ + { + properties: { + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: '${vNetResourceId}/subnets/GatewaySubnet' + } + publicIPAddress: { + id: az.resourceId('Microsoft.Network/publicIPAddresses', gatewayPipName) + } + } + name: 'vNetGatewayConfig1' } - publicIPAddress: { - id: az.resourceId('Microsoft.Network/publicIPAddresses', gatewayPipName) + { + properties: { + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: '${vNetResourceId}/subnets/GatewaySubnet' + } + publicIPAddress: { + id: isActiveActiveValid + ? az.resourceId('Microsoft.Network/publicIPAddresses', activeGatewayPipName) + : az.resourceId('Microsoft.Network/publicIPAddresses', gatewayPipName) + } + } + name: 'vNetGatewayConfig2' } - } - name: 'vNetGatewayConfig1' - } -] - -var vpnClientConfiguration = !empty(clientRootCertData) ? { - vpnClientAddressPool: { - addressPrefixes: [ - vpnClientAddressPoolPrefix ] - } - vpnClientRootCertificates: [ - { - name: 'RootCert1' - properties: { - PublicCertData: clientRootCertData + : [ + { + properties: { + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: '${vNetResourceId}/subnets/GatewaySubnet' + } + publicIPAddress: { + id: az.resourceId('Microsoft.Network/publicIPAddresses', gatewayPipName) + } + } + name: 'vNetGatewayConfig1' } - } - ] - vpnClientRevokedCertificates: !empty(clientRevokedCertThumbprint) ? [ - { - name: 'RevokedCert1' - properties: { - Thumbprint: clientRevokedCertThumbprint + ] + +var vpnClientConfiguration = !empty(clientRootCertData) + ? { + vpnClientAddressPool: { + addressPrefixes: [ + vpnClientAddressPoolPrefix + ] } + vpnClientRootCertificates: [ + { + name: 'RootCert1' + properties: { + PublicCertData: clientRootCertData + } + } + ] + vpnClientRevokedCertificates: !empty(clientRevokedCertThumbprint) + ? [ + { + name: 'RevokedCert1' + properties: { + Thumbprint: clientRevokedCertThumbprint + } + } + ] + : null } - ] : null -} : !empty(vpnClientAadConfiguration) ? { - vpnClientAddressPool: { - addressPrefixes: [ - vpnClientAddressPoolPrefix - ] - } - aadTenant: vpnClientAadConfiguration.aadTenant - aadAudience: vpnClientAadConfiguration.aadAudience - aadIssuer: vpnClientAadConfiguration.aadIssuer - vpnAuthenticationTypes: vpnClientAadConfiguration.vpnAuthenticationTypes - vpnClientProtocols: vpnClientAadConfiguration.vpnClientProtocols -} : null + : !empty(vpnClientAadConfiguration) + ? { + vpnClientAddressPool: { + addressPrefixes: [ + vpnClientAddressPoolPrefix + ] + } + aadTenant: vpnClientAadConfiguration.aadTenant + aadAudience: vpnClientAadConfiguration.aadAudience + aadIssuer: vpnClientAadConfiguration.aadIssuer + vpnAuthenticationTypes: vpnClientAadConfiguration.vpnAuthenticationTypes + vpnClientProtocols: vpnClientAadConfiguration.vpnClientProtocols + } + : null var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + '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') + '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' + ) } // ================// // Deployments // // ================// -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: take('46d3xbcp.res.network-virtualnetworkgateway.${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' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: take( + '46d3xbcp.res.network-virtualnetworkgateway.${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' + } } } } } -} // Public IPs @batchSize(1) -module publicIPAddress 'br/public:avm/res/network/public-ip-address:0.2.0' = [for (virtualGatewayPublicIpName, index) in virtualGatewayPipNameVar: { - name: virtualGatewayPublicIpName - params: { +module publicIPAddress 'br/public:avm/res/network/public-ip-address:0.2.0' = [ + for (virtualGatewayPublicIpName, index) in virtualGatewayPipNameVar: { name: virtualGatewayPublicIpName - diagnosticSettings: publicIpDiagnosticSettings - location: location - lock: lock - publicIPAllocationMethod: gatewayPipAllocationMethod - publicIpPrefixResourceId: !empty(publicIPPrefixResourceId) ? publicIPPrefixResourceId : '' - tags: tags - skuName: gatewayPipSku - zones: contains(zoneRedundantSkus, skuName) ? publicIpZones : [] - dnsSettings: { - domainNameLabel: length(virtualGatewayPipNameVar) == length(domainNameLabel) ? domainNameLabel[index] : virtualGatewayPublicIpName - domainNameLabelScope: '' + params: { + name: virtualGatewayPublicIpName + diagnosticSettings: publicIpDiagnosticSettings + location: location + lock: lock + publicIPAllocationMethod: gatewayPipAllocationMethod + publicIpPrefixResourceId: !empty(publicIPPrefixResourceId) ? publicIPPrefixResourceId : '' + tags: tags + skuName: gatewayPipSku + zones: contains(zoneRedundantSkus, skuName) ? publicIpZones : [] + dnsSettings: { + domainNameLabel: length(virtualGatewayPipNameVar) == length(domainNameLabel) + ? domainNameLabel[index] + : virtualGatewayPublicIpName + domainNameLabelScope: '' + } } } -}] +] // VNET Gateway // ============ @@ -312,9 +341,11 @@ resource virtualNetworkGateway 'Microsoft.Network/virtualNetworkGateways@2023-04 enablePrivateIpAddress: enablePrivateIpAddress enableBgpRouteTranslationForNat: enableBgpRouteTranslationForNat gatewayType: gatewayType - gatewayDefaultSite: !empty(gatewayDefaultSiteLocalNetworkGatewayId) ? { - id: gatewayDefaultSiteLocalNetworkGatewayId - } : null + gatewayDefaultSite: !empty(gatewayDefaultSiteLocalNetworkGatewayId) + ? { + id: gatewayDefaultSiteLocalNetworkGatewayId + } + : null sku: { name: skuName tier: skuName @@ -328,64 +359,81 @@ resource virtualNetworkGateway 'Microsoft.Network/virtualNetworkGateways@2023-04 ] } -module virtualNetworkGateway_natRules 'nat-rule/main.bicep' = [for (natRule, index) in natRules: { - name: '${deployment().name}-NATRule-${index}' - params: { - name: natRule.name - virtualNetworkGatewayName: virtualNetworkGateway.name - externalMappings: contains(natRule, 'externalMappings') ? natRule.externalMappings : [] - internalMappings: contains(natRule, 'internalMappings') ? natRule.internalMappings : [] - ipConfigurationId: contains(natRule, 'ipConfigurationId') ? natRule.ipConfigurationId : '' - mode: contains(natRule, 'mode') ? natRule.mode : '' - type: contains(natRule, 'type') ? natRule.type : '' +module virtualNetworkGateway_natRules 'nat-rule/main.bicep' = [ + for (natRule, index) in natRules: { + name: '${deployment().name}-NATRule-${index}' + params: { + name: natRule.name + virtualNetworkGatewayName: virtualNetworkGateway.name + externalMappings: contains(natRule, 'externalMappings') ? natRule.externalMappings : [] + internalMappings: contains(natRule, 'internalMappings') ? natRule.internalMappings : [] + ipConfigurationId: contains(natRule, 'ipConfigurationId') ? natRule.ipConfigurationId : '' + mode: contains(natRule, 'mode') ? natRule.mode : '' + type: contains(natRule, 'type') ? natRule.type : '' + } } -}] +] -resource virtualNetworkGateway_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.' +resource virtualNetworkGateway_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: virtualNetworkGateway } - scope: virtualNetworkGateway -} -resource virtualNetworkGateway_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource virtualNetworkGateway_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: virtualNetworkGateway } - scope: virtualNetworkGateway -}] +] -resource virtualNetworkGateway_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(virtualNetworkGateway.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource virtualNetworkGateway_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(virtualNetworkGateway.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: virtualNetworkGateway } - scope: virtualNetworkGateway -}] +] // ================// // Outputs // diff --git a/avm/res/network/virtual-network-gateway/main.json b/avm/res/network/virtual-network-gateway/main.json index 19057806a9..f8963435bd 100644 --- a/avm/res/network/virtual-network-gateway/main.json +++ b/avm/res/network/virtual-network-gateway/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17858008949530514784" + "version": "0.26.54.24096", + "templateHash": "11853896150592473268" }, "name": "Virtual Network Gateways", "description": "This module deploys a Virtual Network Gateway.", @@ -1278,8 +1278,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3205216051078222233" + "version": "0.26.54.24096", + "templateHash": "3348839995550946472" }, "name": "VPN Gateway NAT Rules", "description": "This module deploys a Virtual Network Gateway NAT Rule.", diff --git a/avm/res/network/virtual-network-gateway/nat-rule/main.json b/avm/res/network/virtual-network-gateway/nat-rule/main.json index 97aea584a5..f2be904ec8 100644 --- a/avm/res/network/virtual-network-gateway/nat-rule/main.json +++ b/avm/res/network/virtual-network-gateway/nat-rule/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3205216051078222233" + "version": "0.26.54.24096", + "templateHash": "3348839995550946472" }, "name": "VPN Gateway NAT Rules", "description": "This module deploys a Virtual Network Gateway NAT Rule.", diff --git a/avm/res/network/virtual-network-gateway/tests/e2e/aadvpn/main.test.bicep b/avm/res/network/virtual-network-gateway/tests/e2e/aadvpn/main.test.bicep index 67e5c483fe..0a15304be5 100644 --- a/avm/res/network/virtual-network-gateway/tests/e2e/aadvpn/main.test.bicep +++ b/avm/res/network/virtual-network-gateway/tests/e2e/aadvpn/main.test.bicep @@ -45,39 +45,41 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - skuName: 'VpnGw2AZ' - gatewayType: 'Vpn' - vNetResourceId: nestedDependencies.outputs.vnetResourceId - activeActive: false - domainNameLabel: [ - '${namePrefix}-dm-${serviceShort}' - ] - publicIpZones: [ - '1' - '2' - '3' - ] - vpnClientAadConfiguration: { - // The Application ID of the "Azure VPN" Azure AD Enterprise App for Azure Public - aadAudience: '41b23e61-6c1e-4545-b367-cd054e0ed4b4' - aadIssuer: 'https://sts.windows.net/${tenant().tenantId}/' - aadTenant: '${environment().authentication.loginEndpoint}/${tenant().tenantId}/' - vpnAuthenticationTypes: [ - 'AAD' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + skuName: 'VpnGw2AZ' + gatewayType: 'Vpn' + vNetResourceId: nestedDependencies.outputs.vnetResourceId + activeActive: false + domainNameLabel: [ + '${namePrefix}-dm-${serviceShort}' ] - vpnClientProtocols: [ - 'OpenVPN' + publicIpZones: [ + '1' + '2' + '3' ] + vpnClientAadConfiguration: { + // The Application ID of the "Azure VPN" Azure AD Enterprise App for Azure Public + aadAudience: '41b23e61-6c1e-4545-b367-cd054e0ed4b4' + aadIssuer: 'https://sts.windows.net/${tenant().tenantId}/' + aadTenant: '${environment().authentication.loginEndpoint}/${tenant().tenantId}/' + vpnAuthenticationTypes: [ + 'AAD' + ] + vpnClientProtocols: [ + 'OpenVPN' + ] + } + vpnType: 'RouteBased' } - vpnType: 'RouteBased' + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/network/virtual-network-gateway/tests/e2e/defaults/main.test.bicep b/avm/res/network/virtual-network-gateway/tests/e2e/defaults/main.test.bicep index 30e5429e29..9697d73cd0 100644 --- a/avm/res/network/virtual-network-gateway/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/virtual-network-gateway/tests/e2e/defaults/main.test.bicep @@ -47,22 +47,24 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - skuName: 'VpnGw2AZ' - gatewayType: 'Vpn' - vNetResourceId: nestedDependencies.outputs.vnetResourceId - publicIpZones: [ - '1' - '2' - '3' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + skuName: 'VpnGw2AZ' + gatewayType: 'Vpn' + vNetResourceId: nestedDependencies.outputs.vnetResourceId + publicIpZones: [ + '1' + '2' + '3' + ] + } + dependsOn: [ + nestedDependencies ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/network/virtual-network-gateway/tests/e2e/expressRoute/main.test.bicep b/avm/res/network/virtual-network-gateway/tests/e2e/expressRoute/main.test.bicep index 1c6f1816bd..a029c2890a 100644 --- a/avm/res/network/virtual-network-gateway/tests/e2e/expressRoute/main.test.bicep +++ b/avm/res/network/virtual-network-gateway/tests/e2e/expressRoute/main.test.bicep @@ -45,26 +45,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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - skuName: 'ErGw1AZ' - gatewayType: 'ExpressRoute' - vNetResourceId: nestedDependencies.outputs.vnetResourceId - domainNameLabel: [ - '${namePrefix}-dm-${serviceShort}' - ] - gatewayPipName: '${namePrefix}-pip-${serviceShort}' - publicIpZones: [ - '1' - '2' - '3' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + skuName: 'ErGw1AZ' + gatewayType: 'ExpressRoute' + vNetResourceId: nestedDependencies.outputs.vnetResourceId + domainNameLabel: [ + '${namePrefix}-dm-${serviceShort}' + ] + gatewayPipName: '${namePrefix}-pip-${serviceShort}' + publicIpZones: [ + '1' + '2' + '3' + ] + } + dependsOn: [ + nestedDependencies ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/network/virtual-network-gateway/tests/e2e/max/main.test.bicep b/avm/res/network/virtual-network-gateway/tests/e2e/max/main.test.bicep index 74f08061cd..70d7760061 100644 --- a/avm/res/network/virtual-network-gateway/tests/e2e/max/main.test.bicep +++ b/avm/res/network/virtual-network-gateway/tests/e2e/max/main.test.bicep @@ -61,108 +61,113 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - vpnGatewayGeneration: 'Generation2' - skuName: 'VpnGw2AZ' - gatewayType: 'Vpn' - vNetResourceId: nestedDependencies.outputs.vnetResourceId - activeActive: true - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - domainNameLabel: [ - '${namePrefix}-dm-${serviceShort}' - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - publicIpZones: [ - '1' - '2' - '3' - ] - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + vpnGatewayGeneration: 'Generation2' + skuName: 'VpnGw2AZ' + gatewayType: 'Vpn' + vNetResourceId: nestedDependencies.outputs.vnetResourceId + activeActive: true + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + domainNameLabel: [ + '${namePrefix}-dm-${serviceShort}' + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + publicIpZones: [ + '1' + '2' + '3' + ] + 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' + } + ] + vpnType: 'RouteBased' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - vpnType: 'RouteBased' - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + enablePrivateIpAddress: true + gatewayDefaultSiteLocalNetworkGatewayId: nestedDependencies.outputs.localNetworkGatewayResourceId + disableIPSecReplayProtection: true + allowRemoteVnetTraffic: true + natRules: [ + { + name: 'nat-rule-1-static-IngressSnat' + type: 'Static' + mode: 'IngressSnat' + internalMappings: [ + { + addressSpace: '10.100.0.0/24' + portRange: '100' + } + ] + externalMappings: [ + { + addressSpace: '192.168.0.0/24' + portRange: '100' + } + ] + } + { + name: 'nat-rule-2-dynamic-EgressSnat' + type: 'Static' + mode: 'EgressSnat' + internalMappings: [ + { + addressSpace: '172.16.0.0/26' + } + ] + externalMappings: [ + { + addressSpace: '10.200.0.0/26' + } + ] + } + ] + enableBgpRouteTranslationForNat: true } - enablePrivateIpAddress: true - gatewayDefaultSiteLocalNetworkGatewayId: nestedDependencies.outputs.localNetworkGatewayResourceId - disableIPSecReplayProtection: true - allowRemoteVnetTraffic: true - natRules: [ - { - name: 'nat-rule-1-static-IngressSnat' - type: 'Static' - mode: 'IngressSnat' - internalMappings: [ - { - addressSpace: '10.100.0.0/24' - portRange: '100' - } - ] - externalMappings: [ - { - addressSpace: '192.168.0.0/24' - portRange: '100' - } - ] - } - { - name: 'nat-rule-2-dynamic-EgressSnat' - type: 'Static' - mode: 'EgressSnat' - internalMappings: [ - { - addressSpace: '172.16.0.0/26' - } - ] - externalMappings: [ - { - addressSpace: '10.200.0.0/26' - } - ] - } + dependsOn: [ + nestedDependencies + diagnosticDependencies ] - enableBgpRouteTranslationForNat: true } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/network/virtual-network-gateway/tests/e2e/vpn/main.test.bicep b/avm/res/network/virtual-network-gateway/tests/e2e/vpn/main.test.bicep index 7b8dedc495..678b967648 100644 --- a/avm/res/network/virtual-network-gateway/tests/e2e/vpn/main.test.bicep +++ b/avm/res/network/virtual-network-gateway/tests/e2e/vpn/main.test.bicep @@ -46,33 +46,35 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - vpnGatewayGeneration: 'Generation2' - skuName: 'VpnGw2AZ' - gatewayType: 'Vpn' - vNetResourceId: nestedDependencies.outputs.vnetResourceId - activeActive: true - domainNameLabel: [ - '${namePrefix}-dm-${serviceShort}' - ] - publicIpZones: [ - '1' - '2' - '3' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + vpnGatewayGeneration: 'Generation2' + skuName: 'VpnGw2AZ' + gatewayType: 'Vpn' + vNetResourceId: nestedDependencies.outputs.vnetResourceId + activeActive: true + domainNameLabel: [ + '${namePrefix}-dm-${serviceShort}' + ] + publicIpZones: [ + '1' + '2' + '3' + ] + vpnType: 'RouteBased' + enablePrivateIpAddress: true + gatewayDefaultSiteLocalNetworkGatewayId: nestedDependencies.outputs.localNetworkGatewayResourceId + disableIPSecReplayProtection: true + allowRemoteVnetTraffic: true + enableBgpRouteTranslationForNat: true + } + dependsOn: [ + nestedDependencies ] - vpnType: 'RouteBased' - enablePrivateIpAddress: true - gatewayDefaultSiteLocalNetworkGatewayId: nestedDependencies.outputs.localNetworkGatewayResourceId - disableIPSecReplayProtection: true - allowRemoteVnetTraffic: true - enableBgpRouteTranslationForNat: true } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/network/virtual-network-gateway/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/virtual-network-gateway/tests/e2e/waf-aligned/main.test.bicep index 2056a7aeb7..a68a82df32 100644 --- a/avm/res/network/virtual-network-gateway/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/virtual-network-gateway/tests/e2e/waf-aligned/main.test.bicep @@ -59,91 +59,93 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - vpnGatewayGeneration: 'Generation2' - skuName: 'VpnGw2AZ' - gatewayType: 'Vpn' - vNetResourceId: nestedDependencies.outputs.vnetResourceId - activeActive: true - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - domainNameLabel: [ - '${namePrefix}-dm-${serviceShort}' - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - publicIpZones: [ - '1' - '2' - '3' - ] - vpnType: 'RouteBased' - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - enablePrivateIpAddress: true - gatewayDefaultSiteLocalNetworkGatewayId: nestedDependencies.outputs.localNetworkGatewayResourceId - disableIPSecReplayProtection: true - allowRemoteVnetTraffic: true - natRules: [ - { - name: 'nat-rule-1-static-IngressSnat' - type: 'Static' - mode: 'IngressSnat' - internalMappings: [ - { - addressSpace: '10.100.0.0/24' - portRange: '100' - } - ] - externalMappings: [ - { - addressSpace: '192.168.0.0/24' - portRange: '100' - } - ] +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + vpnGatewayGeneration: 'Generation2' + skuName: 'VpnGw2AZ' + gatewayType: 'Vpn' + vNetResourceId: nestedDependencies.outputs.vnetResourceId + activeActive: true + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + domainNameLabel: [ + '${namePrefix}-dm-${serviceShort}' + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - name: 'nat-rule-2-dynamic-EgressSnat' - type: 'Static' - mode: 'EgressSnat' - internalMappings: [ - { - addressSpace: '172.16.0.0/26' - } - ] - externalMappings: [ - { - addressSpace: '10.200.0.0/26' - } - ] + publicIpZones: [ + '1' + '2' + '3' + ] + vpnType: 'RouteBased' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } + enablePrivateIpAddress: true + gatewayDefaultSiteLocalNetworkGatewayId: nestedDependencies.outputs.localNetworkGatewayResourceId + disableIPSecReplayProtection: true + allowRemoteVnetTraffic: true + natRules: [ + { + name: 'nat-rule-1-static-IngressSnat' + type: 'Static' + mode: 'IngressSnat' + internalMappings: [ + { + addressSpace: '10.100.0.0/24' + portRange: '100' + } + ] + externalMappings: [ + { + addressSpace: '192.168.0.0/24' + portRange: '100' + } + ] + } + { + name: 'nat-rule-2-dynamic-EgressSnat' + type: 'Static' + mode: 'EgressSnat' + internalMappings: [ + { + addressSpace: '172.16.0.0/26' + } + ] + externalMappings: [ + { + addressSpace: '10.200.0.0/26' + } + ] + } + ] + enableBgpRouteTranslationForNat: true + } + dependsOn: [ + nestedDependencies + diagnosticDependencies ] - enableBgpRouteTranslationForNat: true } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/network/virtual-network/main.bicep b/avm/res/network/virtual-network/main.bicep index 5a8eaf6be6..e1d6854e1c 100644 --- a/avm/res/network/virtual-network/main.bicep +++ b/avm/res/network/virtual-network/main.bicep @@ -54,34 +54,44 @@ param enableTelemetry bool = true var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + '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') + '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' + ) } // ============ // // Dependencies // // ============ // -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-virtualnetwork.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-virtualnetwork.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { name: name @@ -91,41 +101,61 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { addressSpace: { addressPrefixes: addressPrefixes } - ddosProtectionPlan: !empty(ddosProtectionPlanResourceId) ? { - id: ddosProtectionPlanResourceId - } : null - dhcpOptions: !empty(dnsServers) ? { - dnsServers: array(dnsServers) - } : null + ddosProtectionPlan: !empty(ddosProtectionPlanResourceId) + ? { + id: ddosProtectionPlanResourceId + } + : null + dhcpOptions: !empty(dnsServers) + ? { + dnsServers: array(dnsServers) + } + : null enableDdosProtection: !empty(ddosProtectionPlanResourceId) - encryption: vnetEncryption == true ? { - enabled: vnetEncryption - enforcement: vnetEncryptionEnforcement - } : null + encryption: vnetEncryption == true + ? { + enabled: vnetEncryption + enforcement: vnetEncryptionEnforcement + } + : null flowTimeoutInMinutes: flowTimeoutInMinutes != 0 ? flowTimeoutInMinutes : null - subnets: [for subnet in subnets: { - name: subnet.name - properties: { - addressPrefix: subnet.addressPrefix - addressPrefixes: contains(subnet, 'addressPrefixes') ? subnet.addressPrefixes : [] - applicationGatewayIPConfigurations: contains(subnet, 'applicationGatewayIPConfigurations') ? subnet.applicationGatewayIPConfigurations : [] - delegations: contains(subnet, 'delegations') ? subnet.delegations : [] - ipAllocations: contains(subnet, 'ipAllocations') ? subnet.ipAllocations : [] - natGateway: contains(subnet, 'natGatewayResourceId') ? { - id: subnet.natGatewayResourceId - } : null - networkSecurityGroup: contains(subnet, 'networkSecurityGroupResourceId') ? { - id: subnet.networkSecurityGroupResourceId - } : null - privateEndpointNetworkPolicies: contains(subnet, 'privateEndpointNetworkPolicies') ? subnet.privateEndpointNetworkPolicies : null - privateLinkServiceNetworkPolicies: contains(subnet, 'privateLinkServiceNetworkPolicies') ? subnet.privateLinkServiceNetworkPolicies : null - routeTable: contains(subnet, 'routeTableResourceId') ? { - id: subnet.routeTableResourceId - } : null - serviceEndpoints: contains(subnet, 'serviceEndpoints') ? subnet.serviceEndpoints : [] - serviceEndpointPolicies: contains(subnet, 'serviceEndpointPolicies') ? subnet.serviceEndpointPolicies : [] + subnets: [ + for subnet in subnets: { + name: subnet.name + properties: { + addressPrefix: subnet.addressPrefix + addressPrefixes: contains(subnet, 'addressPrefixes') ? subnet.addressPrefixes : [] + applicationGatewayIPConfigurations: contains(subnet, 'applicationGatewayIPConfigurations') + ? subnet.applicationGatewayIPConfigurations + : [] + delegations: contains(subnet, 'delegations') ? subnet.delegations : [] + ipAllocations: contains(subnet, 'ipAllocations') ? subnet.ipAllocations : [] + natGateway: contains(subnet, 'natGatewayResourceId') + ? { + id: subnet.natGatewayResourceId + } + : null + networkSecurityGroup: contains(subnet, 'networkSecurityGroupResourceId') + ? { + id: subnet.networkSecurityGroupResourceId + } + : null + privateEndpointNetworkPolicies: contains(subnet, 'privateEndpointNetworkPolicies') + ? subnet.privateEndpointNetworkPolicies + : null + privateLinkServiceNetworkPolicies: contains(subnet, 'privateLinkServiceNetworkPolicies') + ? subnet.privateLinkServiceNetworkPolicies + : null + routeTable: contains(subnet, 'routeTableResourceId') + ? { + id: subnet.routeTableResourceId + } + : null + serviceEndpoints: contains(subnet, 'serviceEndpoints') ? subnet.serviceEndpoints : [] + serviceEndpointPolicies: contains(subnet, 'serviceEndpointPolicies') ? subnet.serviceEndpointPolicies : [] + } } - }] + ] } } @@ -137,103 +167,148 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { // You can safely remove the below child module (virtualNetwork_subnets) in your consumption of the module (virtualNetworks) to reduce the template size and duplication. //NOTE End : ------------------------------------ -module virtualNetwork_subnets 'subnet/main.bicep' = [for (subnet, index) in subnets: { - name: '${uniqueString(deployment().name, location)}-subnet-${index}' - params: { - virtualNetworkName: virtualNetwork.name - name: subnet.name - addressPrefix: subnet.addressPrefix - addressPrefixes: contains(subnet, 'addressPrefixes') ? subnet.addressPrefixes : [] - applicationGatewayIPConfigurations: contains(subnet, 'applicationGatewayIPConfigurations') ? subnet.applicationGatewayIPConfigurations : [] - delegations: contains(subnet, 'delegations') ? subnet.delegations : [] - ipAllocations: contains(subnet, 'ipAllocations') ? subnet.ipAllocations : [] - natGatewayResourceId: contains(subnet, 'natGatewayResourceId') ? subnet.natGatewayResourceId : '' - networkSecurityGroupResourceId: contains(subnet, 'networkSecurityGroupResourceId') ? subnet.networkSecurityGroupResourceId : '' - privateEndpointNetworkPolicies: contains(subnet, 'privateEndpointNetworkPolicies') ? subnet.privateEndpointNetworkPolicies : '' - privateLinkServiceNetworkPolicies: contains(subnet, 'privateLinkServiceNetworkPolicies') ? subnet.privateLinkServiceNetworkPolicies : '' - roleAssignments: contains(subnet, 'roleAssignments') ? subnet.roleAssignments : [] - routeTableResourceId: contains(subnet, 'routeTableResourceId') ? subnet.routeTableResourceId : '' - serviceEndpointPolicies: contains(subnet, 'serviceEndpointPolicies') ? subnet.serviceEndpointPolicies : [] - serviceEndpoints: contains(subnet, 'serviceEndpoints') ? subnet.serviceEndpoints : [] +module virtualNetwork_subnets 'subnet/main.bicep' = [ + for (subnet, index) in subnets: { + name: '${uniqueString(deployment().name, location)}-subnet-${index}' + params: { + virtualNetworkName: virtualNetwork.name + name: subnet.name + addressPrefix: subnet.addressPrefix + addressPrefixes: contains(subnet, 'addressPrefixes') ? subnet.addressPrefixes : [] + applicationGatewayIPConfigurations: contains(subnet, 'applicationGatewayIPConfigurations') + ? subnet.applicationGatewayIPConfigurations + : [] + delegations: contains(subnet, 'delegations') ? subnet.delegations : [] + ipAllocations: contains(subnet, 'ipAllocations') ? subnet.ipAllocations : [] + natGatewayResourceId: contains(subnet, 'natGatewayResourceId') ? subnet.natGatewayResourceId : '' + networkSecurityGroupResourceId: contains(subnet, 'networkSecurityGroupResourceId') + ? subnet.networkSecurityGroupResourceId + : '' + privateEndpointNetworkPolicies: contains(subnet, 'privateEndpointNetworkPolicies') + ? subnet.privateEndpointNetworkPolicies + : '' + privateLinkServiceNetworkPolicies: contains(subnet, 'privateLinkServiceNetworkPolicies') + ? subnet.privateLinkServiceNetworkPolicies + : '' + roleAssignments: contains(subnet, 'roleAssignments') ? subnet.roleAssignments : [] + routeTableResourceId: contains(subnet, 'routeTableResourceId') ? subnet.routeTableResourceId : '' + serviceEndpointPolicies: contains(subnet, 'serviceEndpointPolicies') ? subnet.serviceEndpointPolicies : [] + serviceEndpoints: contains(subnet, 'serviceEndpoints') ? subnet.serviceEndpoints : [] + } } -}] +] // Local to Remote peering -module virtualNetwork_peering_local 'virtual-network-peering/main.bicep' = [for (peering, index) in peerings: { - name: '${uniqueString(deployment().name, location)}-virtualNetworkPeering-local-${index}' - params: { - localVnetName: virtualNetwork.name - remoteVirtualNetworkId: peering.remoteVirtualNetworkId - name: contains(peering, 'name') ? peering.name : '${name}-${last(split(peering.remoteVirtualNetworkId, '/'))}' - allowForwardedTraffic: contains(peering, 'allowForwardedTraffic') ? peering.allowForwardedTraffic : true - allowGatewayTransit: contains(peering, 'allowGatewayTransit') ? peering.allowGatewayTransit : false - allowVirtualNetworkAccess: contains(peering, 'allowVirtualNetworkAccess') ? peering.allowVirtualNetworkAccess : true - doNotVerifyRemoteGateways: contains(peering, 'doNotVerifyRemoteGateways') ? peering.doNotVerifyRemoteGateways : true - useRemoteGateways: contains(peering, 'useRemoteGateways') ? peering.useRemoteGateways : false +module virtualNetwork_peering_local 'virtual-network-peering/main.bicep' = [ + for (peering, index) in peerings: { + name: '${uniqueString(deployment().name, location)}-virtualNetworkPeering-local-${index}' + params: { + localVnetName: virtualNetwork.name + remoteVirtualNetworkId: peering.remoteVirtualNetworkId + name: contains(peering, 'name') ? peering.name : '${name}-${last(split(peering.remoteVirtualNetworkId, '/'))}' + allowForwardedTraffic: contains(peering, 'allowForwardedTraffic') ? peering.allowForwardedTraffic : true + allowGatewayTransit: contains(peering, 'allowGatewayTransit') ? peering.allowGatewayTransit : false + allowVirtualNetworkAccess: contains(peering, 'allowVirtualNetworkAccess') + ? peering.allowVirtualNetworkAccess + : true + doNotVerifyRemoteGateways: contains(peering, 'doNotVerifyRemoteGateways') + ? peering.doNotVerifyRemoteGateways + : true + useRemoteGateways: contains(peering, 'useRemoteGateways') ? peering.useRemoteGateways : false + } } -}] +] // Remote to local peering (reverse) -module virtualNetwork_peering_remote 'virtual-network-peering/main.bicep' = [for (peering, index) in peerings: if (contains(peering, 'remotePeeringEnabled') ? peering.remotePeeringEnabled == true : false) { - name: '${uniqueString(deployment().name, location)}-virtualNetworkPeering-remote-${index}' - scope: resourceGroup(split(peering.remoteVirtualNetworkId, '/')[2], split(peering.remoteVirtualNetworkId, '/')[4]) - params: { - localVnetName: last(split(peering.remoteVirtualNetworkId, '/'))! - remoteVirtualNetworkId: virtualNetwork.id - name: contains(peering, 'remotePeeringName') ? peering.remotePeeringName : '${last(split(peering.remoteVirtualNetworkId, '/'))}-${name}' - allowForwardedTraffic: contains(peering, 'remotePeeringAllowForwardedTraffic') ? peering.remotePeeringAllowForwardedTraffic : true - allowGatewayTransit: contains(peering, 'remotePeeringAllowGatewayTransit') ? peering.remotePeeringAllowGatewayTransit : false - allowVirtualNetworkAccess: contains(peering, 'remotePeeringAllowVirtualNetworkAccess') ? peering.remotePeeringAllowVirtualNetworkAccess : true - doNotVerifyRemoteGateways: contains(peering, 'remotePeeringDoNotVerifyRemoteGateways') ? peering.remotePeeringDoNotVerifyRemoteGateways : true - useRemoteGateways: contains(peering, 'remotePeeringUseRemoteGateways') ? peering.remotePeeringUseRemoteGateways : false +module virtualNetwork_peering_remote 'virtual-network-peering/main.bicep' = [ + for (peering, index) in peerings: if (contains(peering, 'remotePeeringEnabled') + ? peering.remotePeeringEnabled == true + : false) { + name: '${uniqueString(deployment().name, location)}-virtualNetworkPeering-remote-${index}' + scope: resourceGroup(split(peering.remoteVirtualNetworkId, '/')[2], split(peering.remoteVirtualNetworkId, '/')[4]) + params: { + localVnetName: last(split(peering.remoteVirtualNetworkId, '/'))! + remoteVirtualNetworkId: virtualNetwork.id + name: contains(peering, 'remotePeeringName') + ? peering.remotePeeringName + : '${last(split(peering.remoteVirtualNetworkId, '/'))}-${name}' + allowForwardedTraffic: contains(peering, 'remotePeeringAllowForwardedTraffic') + ? peering.remotePeeringAllowForwardedTraffic + : true + allowGatewayTransit: contains(peering, 'remotePeeringAllowGatewayTransit') + ? peering.remotePeeringAllowGatewayTransit + : false + allowVirtualNetworkAccess: contains(peering, 'remotePeeringAllowVirtualNetworkAccess') + ? peering.remotePeeringAllowVirtualNetworkAccess + : true + doNotVerifyRemoteGateways: contains(peering, 'remotePeeringDoNotVerifyRemoteGateways') + ? peering.remotePeeringDoNotVerifyRemoteGateways + : true + useRemoteGateways: contains(peering, 'remotePeeringUseRemoteGateways') + ? peering.remotePeeringUseRemoteGateways + : false + } } -}] - -resource virtualNetwork_lock 'Microsoft.Authorization/locks@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.' +] + +resource virtualNetwork_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: virtualNetwork } - scope: virtualNetwork -} -resource virtualNetwork_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource virtualNetwork_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: virtualNetwork } - scope: virtualNetwork -}] - -resource virtualNetwork_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(virtualNetwork.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : roleAssignment.roleDefinitionIdOrName - 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 +] + +resource virtualNetwork_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(virtualNetwork.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : roleAssignment.roleDefinitionIdOrName + 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: virtualNetwork } - scope: virtualNetwork -}] +] @description('The resource group the virtual network was deployed into.') output resourceGroupName string = resourceGroup().name @@ -248,7 +323,9 @@ output name string = virtualNetwork.name output subnetNames array = [for subnet in subnets: subnet.name] @description('The resource IDs of the deployed subnets.') -output subnetResourceIds array = [for subnet in subnets: az.resourceId('Microsoft.Network/virtualNetworks/subnets', name, subnet.name)] +output subnetResourceIds array = [ + for subnet in subnets: az.resourceId('Microsoft.Network/virtualNetworks/subnets', name, subnet.name) +] @description('The location the resource was deployed into.') output location string = virtualNetwork.location diff --git a/avm/res/network/virtual-network/main.json b/avm/res/network/virtual-network/main.json index 755e75f48d..8e3664e661 100644 --- a/avm/res/network/virtual-network/main.json +++ b/avm/res/network/virtual-network/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "10848130532872395336" + "version": "0.26.54.24096", + "templateHash": "11377673418536997302" }, "name": "Virtual Networks", "description": "This module deploys a Virtual Network (vNet).", @@ -523,8 +523,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17033578581013380517" + "version": "0.26.54.24096", + "templateHash": "11309828149329550402" }, "name": "Virtual Network Subnets", "description": "This module deploys a Virtual Network Subnet.", @@ -849,8 +849,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "12334551415753639891" + "version": "0.26.54.24096", + "templateHash": "2926837656927862519" }, "name": "Virtual Network Peerings", "description": "This module deploys a Virtual Network Peering.", @@ -994,8 +994,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "12334551415753639891" + "version": "0.26.54.24096", + "templateHash": "2926837656927862519" }, "name": "Virtual Network Peerings", "description": "This module deploys a Virtual Network Peering.", diff --git a/avm/res/network/virtual-network/subnet/main.bicep b/avm/res/network/virtual-network/subnet/main.bicep index f3b7d07615..bbfc27b1ab 100644 --- a/avm/res/network/virtual-network/subnet/main.bicep +++ b/avm/res/network/virtual-network/subnet/main.bicep @@ -59,11 +59,20 @@ param roleAssignments roleAssignmentType var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + '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') + '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' + ) } resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' existing = { @@ -75,19 +84,27 @@ resource subnet 'Microsoft.Network/virtualNetworks/subnets@2023-04-01' = { parent: virtualNetwork properties: { addressPrefix: addressPrefix - networkSecurityGroup: !empty(networkSecurityGroupResourceId) ? { - id: networkSecurityGroupResourceId - } : null - routeTable: !empty(routeTableResourceId) ? { - id: routeTableResourceId - } : null - natGateway: !empty(natGatewayResourceId) ? { - id: natGatewayResourceId - } : null + networkSecurityGroup: !empty(networkSecurityGroupResourceId) + ? { + id: networkSecurityGroupResourceId + } + : null + routeTable: !empty(routeTableResourceId) + ? { + id: routeTableResourceId + } + : null + natGateway: !empty(natGatewayResourceId) + ? { + id: natGatewayResourceId + } + : null serviceEndpoints: serviceEndpoints delegations: delegations privateEndpointNetworkPolicies: !empty(privateEndpointNetworkPolicies) ? any(privateEndpointNetworkPolicies) : null - privateLinkServiceNetworkPolicies: !empty(privateLinkServiceNetworkPolicies) ? any(privateLinkServiceNetworkPolicies) : null + privateLinkServiceNetworkPolicies: !empty(privateLinkServiceNetworkPolicies) + ? any(privateLinkServiceNetworkPolicies) + : null addressPrefixes: addressPrefixes applicationGatewayIPConfigurations: applicationGatewayIPConfigurations ipAllocations: ipAllocations @@ -95,19 +112,23 @@ resource subnet 'Microsoft.Network/virtualNetworks/subnets@2023-04-01' = { } } -resource subnet_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(subnet.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : roleAssignment.roleDefinitionIdOrName - 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 +resource subnet_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(subnet.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : roleAssignment.roleDefinitionIdOrName + 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: subnet } - scope: subnet -}] +] @description('The resource group the virtual network peering was deployed into.') output resourceGroupName string = resourceGroup().name diff --git a/avm/res/network/virtual-network/subnet/main.json b/avm/res/network/virtual-network/subnet/main.json index 55f868f9fd..4134fdbfa4 100644 --- a/avm/res/network/virtual-network/subnet/main.json +++ b/avm/res/network/virtual-network/subnet/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17033578581013380517" + "version": "0.26.54.24096", + "templateHash": "11309828149329550402" }, "name": "Virtual Network Subnets", "description": "This module deploys a Virtual Network Subnet.", diff --git a/avm/res/network/virtual-network/tests/e2e/defaults/main.test.bicep b/avm/res/network/virtual-network/tests/e2e/defaults/main.test.bicep index c5023d1f86..2c649a41d8 100644 --- a/avm/res/network/virtual-network/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/virtual-network/tests/e2e/defaults/main.test.bicep @@ -36,14 +36,16 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 - addressPrefixes: [ - '10.0.0.0/16' - ] +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 + addressPrefixes: [ + '10.0.0.0/16' + ] + } } -}] +] diff --git a/avm/res/network/virtual-network/tests/e2e/max/main.test.bicep b/avm/res/network/virtual-network/tests/e2e/max/main.test.bicep index 130570f046..0eff43a79d 100644 --- a/avm/res/network/virtual-network/tests/e2e/max/main.test.bicep +++ b/avm/res/network/virtual-network/tests/e2e/max/main.test.bicep @@ -63,109 +63,111 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t var addressPrefix = '10.0.0.0/16' @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 - addressPrefixes: [ - addressPrefix - ] - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - dnsServers: [ - '10.0.1.4' - '10.0.1.5' - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - ] - flowTimeoutInMinutes: 20 - subnets: [ - { - addressPrefix: cidrSubnet(addressPrefix, 24, 0) - name: 'GatewaySubnet' - } - { - addressPrefix: cidrSubnet(addressPrefix, 24, 1) - name: '${namePrefix}-az-subnet-x-001' - networkSecurityGroupResourceId: nestedDependencies.outputs.networkSecurityGroupResourceId - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - ] - routeTableResourceId: nestedDependencies.outputs.routeTableResourceId - serviceEndpoints: [ - { - service: 'Microsoft.Storage' - } - { - service: 'Microsoft.Sql' - } - ] - } - { - addressPrefix: cidrSubnet(addressPrefix, 24, 2) - delegations: [ - { - name: 'netappDel' - properties: { - serviceName: 'Microsoft.Netapp/volumes' +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 + addressPrefixes: [ + addressPrefix + ] + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' } - } - ] - name: '${namePrefix}-az-subnet-x-002' - networkSecurityGroupResourceId: nestedDependencies.outputs.networkSecurityGroupResourceId - } - { - addressPrefix: cidrSubnet(addressPrefix, 24, 3) - name: '${namePrefix}-az-subnet-x-003' - networkSecurityGroupResourceId: nestedDependencies.outputs.networkSecurityGroupResourceId - privateEndpointNetworkPolicies: 'Disabled' - privateLinkServiceNetworkPolicies: 'Enabled' + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + dnsServers: [ + '10.0.1.4' + '10.0.1.5' + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - addressPrefix: cidrSubnet(addressPrefix, 24, 4) - name: 'AzureBastionSubnet' - networkSecurityGroupResourceId: nestedDependencies.outputs.networkSecurityGroupBastionResourceId - } - { - addressPrefix: cidrSubnet(addressPrefix, 24, 5) - name: 'AzureFirewallSubnet' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + flowTimeoutInMinutes: 20 + subnets: [ + { + addressPrefix: cidrSubnet(addressPrefix, 24, 0) + name: 'GatewaySubnet' + } + { + addressPrefix: cidrSubnet(addressPrefix, 24, 1) + name: '${namePrefix}-az-subnet-x-001' + networkSecurityGroupResourceId: nestedDependencies.outputs.networkSecurityGroupResourceId + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + routeTableResourceId: nestedDependencies.outputs.routeTableResourceId + serviceEndpoints: [ + { + service: 'Microsoft.Storage' + } + { + service: 'Microsoft.Sql' + } + ] + } + { + addressPrefix: cidrSubnet(addressPrefix, 24, 2) + delegations: [ + { + name: 'netappDel' + properties: { + serviceName: 'Microsoft.Netapp/volumes' + } + } + ] + name: '${namePrefix}-az-subnet-x-002' + networkSecurityGroupResourceId: nestedDependencies.outputs.networkSecurityGroupResourceId + } + { + addressPrefix: cidrSubnet(addressPrefix, 24, 3) + name: '${namePrefix}-az-subnet-x-003' + networkSecurityGroupResourceId: nestedDependencies.outputs.networkSecurityGroupResourceId + privateEndpointNetworkPolicies: 'Disabled' + privateLinkServiceNetworkPolicies: 'Enabled' + } + { + addressPrefix: cidrSubnet(addressPrefix, 24, 4) + name: 'AzureBastionSubnet' + networkSecurityGroupResourceId: nestedDependencies.outputs.networkSecurityGroupBastionResourceId + } + { + addressPrefix: cidrSubnet(addressPrefix, 24, 5) + name: 'AzureFirewallSubnet' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/network/virtual-network/tests/e2e/vnetPeering/main.test.bicep b/avm/res/network/virtual-network/tests/e2e/vnetPeering/main.test.bicep index 9acbeebb62..cbb86623e3 100644 --- a/avm/res/network/virtual-network/tests/e2e/vnetPeering/main.test.bicep +++ b/avm/res/network/virtual-network/tests/e2e/vnetPeering/main.test.bicep @@ -46,50 +46,52 @@ 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 - addressPrefixes: [ - '10.1.0.0/24' - ] - subnets: [ - { - addressPrefix: '10.1.0.0/26' - name: 'GatewaySubnet' - } - { - addressPrefix: '10.1.0.64/26' - name: 'AzureBastionSubnet' - networkSecurityGroupResourceId: nestedDependencies.outputs.networkSecurityGroupBastionResourceId +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 + addressPrefixes: [ + '10.1.0.0/24' + ] + subnets: [ + { + addressPrefix: '10.1.0.0/26' + name: 'GatewaySubnet' + } + { + addressPrefix: '10.1.0.64/26' + name: 'AzureBastionSubnet' + networkSecurityGroupResourceId: nestedDependencies.outputs.networkSecurityGroupBastionResourceId + } + { + addressPrefix: '10.1.0.128/26' + name: 'AzureFirewallSubnet' + } + ] + peerings: [ + { + allowForwardedTraffic: true + allowGatewayTransit: false + allowVirtualNetworkAccess: true + remotePeeringAllowForwardedTraffic: true + remotePeeringAllowVirtualNetworkAccess: true + remotePeeringEnabled: true + remotePeeringName: 'customName' + remoteVirtualNetworkId: nestedDependencies.outputs.virtualNetworkResourceId + useRemoteGateways: false + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - { - addressPrefix: '10.1.0.128/26' - name: 'AzureFirewallSubnet' - } - ] - peerings: [ - { - allowForwardedTraffic: true - allowGatewayTransit: false - allowVirtualNetworkAccess: true - remotePeeringAllowForwardedTraffic: true - remotePeeringAllowVirtualNetworkAccess: true - remotePeeringEnabled: true - remotePeeringName: 'customName' - remoteVirtualNetworkId: nestedDependencies.outputs.virtualNetworkResourceId - useRemoteGateways: false - } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/network/virtual-network/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/virtual-network/tests/e2e/waf-aligned/main.test.bicep index d1063b5fdc..b5f66c589d 100644 --- a/avm/res/network/virtual-network/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/virtual-network/tests/e2e/waf-aligned/main.test.bicep @@ -63,102 +63,104 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t var addressPrefix = '10.0.0.0/16' @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 - addressPrefixes: [ - addressPrefix - ] - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - dnsServers: [ - '10.0.1.4' - '10.0.1.5' - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - flowTimeoutInMinutes: 20 - subnets: [ - { - addressPrefix: cidrSubnet(addressPrefix, 24, 0) - name: 'GatewaySubnet' - } - { - addressPrefix: cidrSubnet(addressPrefix, 24, 1) - name: '${namePrefix}-az-subnet-x-001' - networkSecurityGroupResourceId: nestedDependencies.outputs.networkSecurityGroupResourceId - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - ] - routeTableResourceId: nestedDependencies.outputs.routeTableResourceId - serviceEndpoints: [ - { - service: 'Microsoft.Storage' - } - { - service: 'Microsoft.Sql' - } - ] - } - { - addressPrefix: cidrSubnet(addressPrefix, 24, 2) - delegations: [ - { - name: 'netappDel' - properties: { - serviceName: 'Microsoft.Netapp/volumes' +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 + addressPrefixes: [ + addressPrefix + ] + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' } - } - ] - name: '${namePrefix}-az-subnet-x-002' - networkSecurityGroupResourceId: nestedDependencies.outputs.networkSecurityGroupResourceId - } - { - addressPrefix: cidrSubnet(addressPrefix, 24, 3) - name: '${namePrefix}-az-subnet-x-003' - networkSecurityGroupResourceId: nestedDependencies.outputs.networkSecurityGroupResourceId - privateEndpointNetworkPolicies: 'Disabled' - privateLinkServiceNetworkPolicies: 'Enabled' - } - { - addressPrefix: cidrSubnet(addressPrefix, 24, 4) - name: 'AzureBastionSubnet' - networkSecurityGroupResourceId: nestedDependencies.outputs.networkSecurityGroupBastionResourceId + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + dnsServers: [ + '10.0.1.4' + '10.0.1.5' + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - addressPrefix: cidrSubnet(addressPrefix, 24, 5) - name: 'AzureFirewallSubnet' + flowTimeoutInMinutes: 20 + subnets: [ + { + addressPrefix: cidrSubnet(addressPrefix, 24, 0) + name: 'GatewaySubnet' + } + { + addressPrefix: cidrSubnet(addressPrefix, 24, 1) + name: '${namePrefix}-az-subnet-x-001' + networkSecurityGroupResourceId: nestedDependencies.outputs.networkSecurityGroupResourceId + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + routeTableResourceId: nestedDependencies.outputs.routeTableResourceId + serviceEndpoints: [ + { + service: 'Microsoft.Storage' + } + { + service: 'Microsoft.Sql' + } + ] + } + { + addressPrefix: cidrSubnet(addressPrefix, 24, 2) + delegations: [ + { + name: 'netappDel' + properties: { + serviceName: 'Microsoft.Netapp/volumes' + } + } + ] + name: '${namePrefix}-az-subnet-x-002' + networkSecurityGroupResourceId: nestedDependencies.outputs.networkSecurityGroupResourceId + } + { + addressPrefix: cidrSubnet(addressPrefix, 24, 3) + name: '${namePrefix}-az-subnet-x-003' + networkSecurityGroupResourceId: nestedDependencies.outputs.networkSecurityGroupResourceId + privateEndpointNetworkPolicies: 'Disabled' + privateLinkServiceNetworkPolicies: 'Enabled' + } + { + addressPrefix: cidrSubnet(addressPrefix, 24, 4) + name: 'AzureBastionSubnet' + networkSecurityGroupResourceId: nestedDependencies.outputs.networkSecurityGroupBastionResourceId + } + { + addressPrefix: cidrSubnet(addressPrefix, 24, 5) + name: 'AzureFirewallSubnet' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/network/virtual-network/virtual-network-peering/main.json b/avm/res/network/virtual-network/virtual-network-peering/main.json index 2c6b4fadea..b28eeb4471 100644 --- a/avm/res/network/virtual-network/virtual-network-peering/main.json +++ b/avm/res/network/virtual-network/virtual-network-peering/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "12334551415753639891" + "version": "0.26.54.24096", + "templateHash": "2926837656927862519" }, "name": "Virtual Network Peerings", "description": "This module deploys a Virtual Network Peering.", diff --git a/avm/res/network/virtual-wan/main.bicep b/avm/res/network/virtual-wan/main.bicep index c130a7eae3..c3c2777288 100644 --- a/avm/res/network/virtual-wan/main.bicep +++ b/avm/res/network/virtual-wan/main.bicep @@ -38,30 +38,40 @@ param lock lockType var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + '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') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-virtualwan.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.network-virtualwan.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource virtualWan 'Microsoft.Network/virtualWans@2023-04-01' = { name: name @@ -75,28 +85,37 @@ resource virtualWan 'Microsoft.Network/virtualWans@2023-04-01' = { } } -resource virtualWan_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.' +resource virtualWan_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: virtualWan } - scope: virtualWan -} -resource networkInterface_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(virtualWan.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource networkInterface_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(virtualWan.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: virtualWan } - scope: virtualWan -}] +] @description('The name of the virtual WAN.') output name string = virtualWan.name diff --git a/avm/res/network/virtual-wan/main.json b/avm/res/network/virtual-wan/main.json index 4bdfcb62dc..5b286a4756 100644 --- a/avm/res/network/virtual-wan/main.json +++ b/avm/res/network/virtual-wan/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "5785178353049312317" + "version": "0.26.54.24096", + "templateHash": "8898881452138081725" }, "name": "Virtual WANs", "description": "This module deploys a Virtual WAN.", diff --git a/avm/res/network/virtual-wan/tests/e2e/defaults/main.test.bicep b/avm/res/network/virtual-wan/tests/e2e/defaults/main.test.bicep index 02d9cb1c28..4a655c13bf 100644 --- a/avm/res/network/virtual-wan/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/virtual-wan/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 +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 + } } -}] +] diff --git a/avm/res/network/virtual-wan/tests/e2e/max/dependencies.bicep b/avm/res/network/virtual-wan/tests/e2e/max/dependencies.bicep index 2ab8334b56..9f6d367115 100644 --- a/avm/res/network/virtual-wan/tests/e2e/max/dependencies.bicep +++ b/avm/res/network/virtual-wan/tests/e2e/max/dependencies.bicep @@ -5,8 +5,8 @@ param resourceLocation string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: resourceLocation + name: managedIdentityName + location: resourceLocation } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/network/virtual-wan/tests/e2e/max/main.test.bicep b/avm/res/network/virtual-wan/tests/e2e/max/main.test.bicep index ba7df165ee..909f2c7969 100644 --- a/avm/res/network/virtual-wan/tests/e2e/max/main.test.bicep +++ b/avm/res/network/virtual-wan/tests/e2e/max/main.test.bicep @@ -45,44 +45,49 @@ 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 - allowBranchToBranchTraffic: true - allowVnetToVnetTraffic: true - disableVpnEncryption: true - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +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 + allowBranchToBranchTraffic: true + allowVnetToVnetTraffic: true + disableVpnEncryption: true + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + 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' + } + ] + type: 'Basic' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - ] - type: 'Basic' - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/network/virtual-wan/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/network/virtual-wan/tests/e2e/waf-aligned/dependencies.bicep index a7f42aee7b..7be39e253a 100644 --- a/avm/res/network/virtual-wan/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/network/virtual-wan/tests/e2e/waf-aligned/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/network/virtual-wan/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/virtual-wan/tests/e2e/waf-aligned/main.test.bicep index 9ccbb889d3..bed35b64ae 100644 --- a/avm/res/network/virtual-wan/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/virtual-wan/tests/e2e/waf-aligned/main.test.bicep @@ -45,23 +45,25 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - allowBranchToBranchTraffic: true - allowVnetToVnetTraffic: true - disableVpnEncryption: true - type: 'Basic' - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + allowBranchToBranchTraffic: true + allowVnetToVnetTraffic: true + disableVpnEncryption: true + type: 'Basic' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/network/vpn-gateway/main.bicep b/avm/res/network/vpn-gateway/main.bicep index 436d997355..b917b16560 100644 --- a/avm/res/network/vpn-gateway/main.bicep +++ b/avm/res/network/vpn-gateway/main.bicep @@ -38,23 +38,27 @@ param lock lockType @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: take('46d3xbcp.res.network-vpngateway.${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' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: take( + '46d3xbcp.res.network-vpngateway.${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' + } } } } } -} resource vpnGateway 'Microsoft.Network/vpnGateways@2023-04-01' = { name: name @@ -65,75 +69,86 @@ resource vpnGateway 'Microsoft.Network/vpnGateways@2023-04-01' = { enableBgpRouteTranslationForNat: enableBgpRouteTranslationForNat isRoutingPreferenceInternet: isRoutingPreferenceInternet vpnGatewayScaleUnit: vpnGatewayScaleUnit - connections: [for (connection, index) in vpnConnections: { - name: connection.name - properties: { - connectionBandwidth: connection.?connectionBandwidth - enableBgp: connection.?enableBgp - enableInternetSecurity: connection.?enableInternetSecurity - remoteVpnSite: contains(connection, 'remoteVpnSiteResourceId') ? { - id: connection.remoteVpnSiteResourceId - } : null - enableRateLimiting: connection.?enableRateLimiting - routingConfiguration: connection.?routingConfiguration - routingWeight: connection.?routingWeight - sharedKey: connection.?sharedKey - useLocalAzureIpAddress: connection.?useLocalAzureIpAddress - usePolicyBasedTrafficSelectors: connection.?usePolicyBasedTrafficSelectors - vpnConnectionProtocolType: connection.?vpnConnectionProtocolType - ipsecPolicies: connection.?ipsecPolicies - trafficSelectorPolicies: connection.?trafficSelectorPolicies - vpnLinkConnections: connection.?vpnLinkConnections + connections: [ + for (connection, index) in vpnConnections: { + name: connection.name + properties: { + connectionBandwidth: connection.?connectionBandwidth + enableBgp: connection.?enableBgp + enableInternetSecurity: connection.?enableInternetSecurity + remoteVpnSite: contains(connection, 'remoteVpnSiteResourceId') + ? { + id: connection.remoteVpnSiteResourceId + } + : null + enableRateLimiting: connection.?enableRateLimiting + routingConfiguration: connection.?routingConfiguration + routingWeight: connection.?routingWeight + sharedKey: connection.?sharedKey + useLocalAzureIpAddress: connection.?useLocalAzureIpAddress + usePolicyBasedTrafficSelectors: connection.?usePolicyBasedTrafficSelectors + vpnConnectionProtocolType: connection.?vpnConnectionProtocolType + ipsecPolicies: connection.?ipsecPolicies + trafficSelectorPolicies: connection.?trafficSelectorPolicies + vpnLinkConnections: connection.?vpnLinkConnections + } } - }] + ] virtualHub: { id: virtualHubResourceId } } } -resource vpnGateway_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.' +resource vpnGateway_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: vpnGateway } - scope: vpnGateway -} -module vpnGateway_natRules 'nat-rule/main.bicep' = [for (natRule, index) in natRules: { - name: '${deployment().name}-NATRule-${index}' - params: { - name: natRule.name - vpnGatewayName: vpnGateway.name - externalMappings: contains(natRule, 'externalMappings') ? natRule.externalMappings : [] - internalMappings: contains(natRule, 'internalMappings') ? natRule.internalMappings : [] - ipConfigurationId: contains(natRule, 'ipConfigurationId') ? natRule.ipConfigurationId : '' - mode: natRule.?mode - type: natRule.?type +module vpnGateway_natRules 'nat-rule/main.bicep' = [ + for (natRule, index) in natRules: { + name: '${deployment().name}-NATRule-${index}' + params: { + name: natRule.name + vpnGatewayName: vpnGateway.name + externalMappings: contains(natRule, 'externalMappings') ? natRule.externalMappings : [] + internalMappings: contains(natRule, 'internalMappings') ? natRule.internalMappings : [] + ipConfigurationId: contains(natRule, 'ipConfigurationId') ? natRule.ipConfigurationId : '' + mode: natRule.?mode + type: natRule.?type + } } -}] - -module vpnGateway_vpnConnections 'vpn-connection/main.bicep' = [for (connection, index) in vpnConnections: { - name: '${deployment().name}-Connection-${index}' - params: { - name: connection.name - vpnGatewayName: vpnGateway.name - connectionBandwidth: connection.?connectionBandwidth - enableBgp: connection.?enableBgp - enableInternetSecurity: connection.?enableInternetSecurity - remoteVpnSiteResourceId: connection.?remoteVpnSiteResourceId - enableRateLimiting: connection.?enableRateLimiting - routingConfiguration: connection.?routingConfiguration - routingWeight: connection.?routingWeight - sharedKey: connection.?sharedKey - useLocalAzureIpAddress: connection.?useLocalAzureIpAddress - usePolicyBasedTrafficSelectors: connection.?usePolicyBasedTrafficSelectors - vpnConnectionProtocolType: connection.?vpnConnectionProtocolType - trafficSelectorPolicies: connection.?trafficSelectorPolicies - vpnLinkConnections: connection.?vpnLinkConnections +] + +module vpnGateway_vpnConnections 'vpn-connection/main.bicep' = [ + for (connection, index) in vpnConnections: { + name: '${deployment().name}-Connection-${index}' + params: { + name: connection.name + vpnGatewayName: vpnGateway.name + connectionBandwidth: connection.?connectionBandwidth + enableBgp: connection.?enableBgp + enableInternetSecurity: connection.?enableInternetSecurity + remoteVpnSiteResourceId: connection.?remoteVpnSiteResourceId + enableRateLimiting: connection.?enableRateLimiting + routingConfiguration: connection.?routingConfiguration + routingWeight: connection.?routingWeight + sharedKey: connection.?sharedKey + useLocalAzureIpAddress: connection.?useLocalAzureIpAddress + usePolicyBasedTrafficSelectors: connection.?usePolicyBasedTrafficSelectors + vpnConnectionProtocolType: connection.?vpnConnectionProtocolType + trafficSelectorPolicies: connection.?trafficSelectorPolicies + vpnLinkConnections: connection.?vpnLinkConnections + } } -}] +] @description('The name of the VPN gateway.') output name string = vpnGateway.name diff --git a/avm/res/network/vpn-gateway/main.json b/avm/res/network/vpn-gateway/main.json index 515119c148..57d805dbfa 100644 --- a/avm/res/network/vpn-gateway/main.json +++ b/avm/res/network/vpn-gateway/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "18311728331837293497" + "version": "0.26.54.24096", + "templateHash": "16246563114829739207" }, "name": "VPN Gateways", "description": "This module deploys a VPN Gateway.", @@ -235,8 +235,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "10009969919084019961" + "version": "0.26.54.24096", + "templateHash": "15540036539979482149" }, "name": "VPN Gateway NAT Rules", "description": "This module deploys a VPN Gateway NAT Rule.", @@ -417,8 +417,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2523279657002252302" + "version": "0.26.54.24096", + "templateHash": "13703101435058090684" }, "name": "VPN Gateway VPN Connections", "description": "This module deploys a VPN Gateway VPN Connection.", diff --git a/avm/res/network/vpn-gateway/nat-rule/main.json b/avm/res/network/vpn-gateway/nat-rule/main.json index 8cb6ebdcd5..efeb649095 100644 --- a/avm/res/network/vpn-gateway/nat-rule/main.json +++ b/avm/res/network/vpn-gateway/nat-rule/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "10009969919084019961" + "version": "0.26.54.24096", + "templateHash": "15540036539979482149" }, "name": "VPN Gateway NAT Rules", "description": "This module deploys a VPN Gateway NAT Rule.", diff --git a/avm/res/network/vpn-gateway/tests/e2e/defaults/main.test.bicep b/avm/res/network/vpn-gateway/tests/e2e/defaults/main.test.bicep index f87549450c..8debc2b069 100644 --- a/avm/res/network/vpn-gateway/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/vpn-gateway/tests/e2e/defaults/main.test.bicep @@ -46,15 +46,17 @@ 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: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - virtualHubResourceId: nestedDependencies.outputs.virtualHubResourceId +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + virtualHubResourceId: nestedDependencies.outputs.virtualHubResourceId + } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/network/vpn-gateway/tests/e2e/max/main.test.bicep b/avm/res/network/vpn-gateway/tests/e2e/max/main.test.bicep index 57f89afa57..b51c76ee82 100644 --- a/avm/res/network/vpn-gateway/tests/e2e/max/main.test.bicep +++ b/avm/res/network/vpn-gateway/tests/e2e/max/main.test.bicep @@ -46,59 +46,61 @@ module nestedDependencies 'dependencies.bicep' = { // Test Execution // // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - virtualHubResourceId: nestedDependencies.outputs.virtualHubResourceId - bgpSettings: { - asn: 65515 - peerWeight: 0 - } - vpnConnections: [ - { - connectionBandwidth: 100 - enableBgp: false - name: 'Connection-${last(split(nestedDependencies.outputs.vpnSiteResourceId, '/'))}' - remoteVpnSiteResourceId: nestedDependencies.outputs.vpnSiteResourceId - enableInternetSecurity: true - vpnConnectionProtocolType: 'IKEv2' - enableRateLimiting: false - useLocalAzureIpAddress: false - usePolicyBasedTrafficSelectors: false - routingWeight: 0 +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + virtualHubResourceId: nestedDependencies.outputs.virtualHubResourceId + bgpSettings: { + asn: 65515 + peerWeight: 0 } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - natRules: [ - { - externalMappings: [ - { - addressSpace: '192.168.21.0/24' - } - ] - internalMappings: [ - { - addressSpace: '10.4.0.0/24' - } - ] - mode: 'EgressSnat' - name: 'natRule1' - type: 'Static' + vpnConnections: [ + { + connectionBandwidth: 100 + enableBgp: false + name: 'Connection-${last(split(nestedDependencies.outputs.vpnSiteResourceId, '/'))}' + remoteVpnSiteResourceId: nestedDependencies.outputs.vpnSiteResourceId + enableInternetSecurity: true + vpnConnectionProtocolType: 'IKEv2' + enableRateLimiting: false + useLocalAzureIpAddress: false + usePolicyBasedTrafficSelectors: false + routingWeight: 0 + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + natRules: [ + { + externalMappings: [ + { + addressSpace: '192.168.21.0/24' + } + ] + internalMappings: [ + { + addressSpace: '10.4.0.0/24' + } + ] + mode: 'EgressSnat' + name: 'natRule1' + type: 'Static' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/network/vpn-gateway/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/vpn-gateway/tests/e2e/waf-aligned/main.test.bicep index 69c900d82b..5213b39d56 100644 --- a/avm/res/network/vpn-gateway/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/vpn-gateway/tests/e2e/waf-aligned/main.test.bicep @@ -46,59 +46,61 @@ module nestedDependencies 'dependencies.bicep' = { // Test Execution // // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - virtualHubResourceId: nestedDependencies.outputs.virtualHubResourceId - bgpSettings: { - asn: 65515 - peerWeight: 0 - } - vpnConnections: [ - { - connectionBandwidth: 100 - enableBgp: false - name: 'Connection-${last(split(nestedDependencies.outputs.vpnSiteResourceId, '/'))}' - remoteVpnSiteResourceId: nestedDependencies.outputs.vpnSiteResourceId - enableInternetSecurity: true - vpnConnectionProtocolType: 'IKEv2' - enableRateLimiting: false - useLocalAzureIpAddress: false - usePolicyBasedTrafficSelectors: false - routingWeight: 0 +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}001' + virtualHubResourceId: nestedDependencies.outputs.virtualHubResourceId + bgpSettings: { + asn: 65515 + peerWeight: 0 } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - natRules: [ - { - externalMappings: [ - { - addressSpace: '192.168.21.0/24' - } - ] - internalMappings: [ - { - addressSpace: '10.4.0.0/24' - } - ] - mode: 'EgressSnat' - name: 'natRule1' - type: 'Static' + vpnConnections: [ + { + connectionBandwidth: 100 + enableBgp: false + name: 'Connection-${last(split(nestedDependencies.outputs.vpnSiteResourceId, '/'))}' + remoteVpnSiteResourceId: nestedDependencies.outputs.vpnSiteResourceId + enableInternetSecurity: true + vpnConnectionProtocolType: 'IKEv2' + enableRateLimiting: false + useLocalAzureIpAddress: false + usePolicyBasedTrafficSelectors: false + routingWeight: 0 + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + natRules: [ + { + externalMappings: [ + { + addressSpace: '192.168.21.0/24' + } + ] + internalMappings: [ + { + addressSpace: '10.4.0.0/24' + } + ] + mode: 'EgressSnat' + name: 'natRule1' + type: 'Static' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/network/vpn-gateway/vpn-connection/main.bicep b/avm/res/network/vpn-gateway/vpn-connection/main.bicep index f189154ce4..3f3bb8beac 100644 --- a/avm/res/network/vpn-gateway/vpn-connection/main.bicep +++ b/avm/res/network/vpn-gateway/vpn-connection/main.bicep @@ -68,9 +68,11 @@ resource vpnConnection 'Microsoft.Network/vpnGateways/vpnConnections@2023-04-01' enableInternetSecurity: enableInternetSecurity enableRateLimiting: enableRateLimiting ipsecPolicies: ipsecPolicies - remoteVpnSite: !empty(remoteVpnSiteResourceId) ? { - id: remoteVpnSiteResourceId - } : null + remoteVpnSite: !empty(remoteVpnSiteResourceId) + ? { + id: remoteVpnSiteResourceId + } + : null routingConfiguration: routingConfiguration routingWeight: routingWeight sharedKey: sharedKey diff --git a/avm/res/network/vpn-gateway/vpn-connection/main.json b/avm/res/network/vpn-gateway/vpn-connection/main.json index 7ec547d29d..06889f1399 100644 --- a/avm/res/network/vpn-gateway/vpn-connection/main.json +++ b/avm/res/network/vpn-gateway/vpn-connection/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2523279657002252302" + "version": "0.26.54.24096", + "templateHash": "13703101435058090684" }, "name": "VPN Gateway VPN Connections", "description": "This module deploys a VPN Gateway VPN Connection.", diff --git a/avm/res/network/vpn-site/main.bicep b/avm/res/network/vpn-site/main.bicep index 4b5c0354d6..d2ff28fcf8 100644 --- a/avm/res/network/vpn-site/main.bicep +++ b/avm/res/network/vpn-site/main.bicep @@ -46,39 +46,54 @@ param roleAssignments roleAssignmentType var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + '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') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: take('46d3xbcp.res.network-vpnsite.${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' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: take( + '46d3xbcp.res.network-vpnsite.${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' + } } } } } -} resource vpnSite 'Microsoft.Network/vpnSites@2023-04-01' = { name: name location: location tags: tags properties: { - addressSpace: !empty(addressPrefixes) ? { - addressPrefixes: addressPrefixes - } : null + addressSpace: !empty(addressPrefixes) + ? { + addressPrefixes: addressPrefixes + } + : null bgpProperties: !empty(bgpProperties) ? bgpProperties : null deviceProperties: !empty(deviceProperties) ? deviceProperties : null ipAddress: !empty(ipAddress) ? ipAddress : null @@ -91,28 +106,37 @@ resource vpnSite 'Microsoft.Network/vpnSites@2023-04-01' = { } } -resource vpnSite_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.' +resource vpnSite_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: vpnSite } - scope: vpnSite -} -resource vpnSite_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(vpnSite.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource vpnSite_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(vpnSite.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: vpnSite } - scope: vpnSite -}] +] @description('The name of the VPN site.') output name string = vpnSite.name diff --git a/avm/res/network/vpn-site/main.json b/avm/res/network/vpn-site/main.json index 158bb5fe53..fb99d8c873 100644 --- a/avm/res/network/vpn-site/main.json +++ b/avm/res/network/vpn-site/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "15929978987009174743" + "version": "0.26.54.24096", + "templateHash": "14637032224635942457" }, "name": "VPN Sites", "description": "This module deploys a VPN Site.", diff --git a/avm/res/network/vpn-site/tests/e2e/defaults/main.test.bicep b/avm/res/network/vpn-site/tests/e2e/defaults/main.test.bicep index 40b66391a9..4818c6fb53 100644 --- a/avm/res/network/vpn-site/tests/e2e/defaults/main.test.bicep +++ b/avm/res/network/vpn-site/tests/e2e/defaults/main.test.bicep @@ -45,19 +45,21 @@ 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: { - location: resourceLocation - name: '${namePrefix}-${serviceShort}' - virtualWanId: nestedDependencies.outputs.virtualWWANResourceId - addressPrefixes: [ - '10.0.0.0/16' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}-${serviceShort}' + virtualWanId: nestedDependencies.outputs.virtualWWANResourceId + addressPrefixes: [ + '10.0.0.0/16' + ] + ipAddress: '1.2.3.4' + } + dependsOn: [ + nestedDependencies ] - ipAddress: '1.2.3.4' } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/network/vpn-site/tests/e2e/max/main.test.bicep b/avm/res/network/vpn-site/tests/e2e/max/main.test.bicep index bc4ee85f75..bd72eae845 100644 --- a/avm/res/network/vpn-site/tests/e2e/max/main.test.bicep +++ b/avm/res/network/vpn-site/tests/e2e/max/main.test.bicep @@ -46,81 +46,86 @@ 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: { - location: resourceLocation - name: '${namePrefix}-${serviceShort}' - virtualWanId: nestedDependencies.outputs.virtualWWANResourceId - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - tags: { - 'hidden-title': 'This is visible in the resource name' - tagA: 'valueA' - tagB: 'valueB' - } - deviceProperties: { - linkSpeedInMbps: 0 - } - vpnSiteLinks: [ - { - name: '${namePrefix}-vSite-${serviceShort}' - properties: { - bgpProperties: { - asn: 65010 - bgpPeeringAddress: '1.1.1.1' - } - ipAddress: '1.2.3.4' - linkProperties: { - linkProviderName: 'contoso' - linkSpeedInMbps: 5 - } - } +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}-${serviceShort}' + virtualWanId: nestedDependencies.outputs.virtualWWANResourceId + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + tags: { + 'hidden-title': 'This is visible in the resource name' + tagA: 'valueA' + tagB: 'valueB' + } + deviceProperties: { + linkSpeedInMbps: 0 } - { - name: 'Link1' - properties: { - bgpProperties: { - asn: 65020 - bgpPeeringAddress: '192.168.1.0' + vpnSiteLinks: [ + { + name: '${namePrefix}-vSite-${serviceShort}' + properties: { + bgpProperties: { + asn: 65010 + bgpPeeringAddress: '1.1.1.1' + } + ipAddress: '1.2.3.4' + linkProperties: { + linkProviderName: 'contoso' + linkSpeedInMbps: 5 + } } - ipAddress: '2.2.2.2' - linkProperties: { - linkProviderName: 'contoso' - linkSpeedInMbps: 5 + } + { + name: 'Link1' + properties: { + bgpProperties: { + asn: 65020 + bgpPeeringAddress: '192.168.1.0' + } + ipAddress: '2.2.2.2' + linkProperties: { + linkProviderName: 'contoso' + linkSpeedInMbps: 5 + } } } + ] + o365Policy: { + breakOutCategories: { + optimize: true + allow: true + default: true + } } - ] - o365Policy: { - breakOutCategories: { - optimize: true - allow: true - default: true - } + 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' + } + ] } - 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' - } + dependsOn: [ + nestedDependencies ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/network/vpn-site/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/vpn-site/tests/e2e/waf-aligned/main.test.bicep index 89d8b6d746..5f582100f2 100644 --- a/avm/res/network/vpn-site/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/network/vpn-site/tests/e2e/waf-aligned/main.test.bicep @@ -46,64 +46,66 @@ 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: { - location: resourceLocation - name: '${namePrefix}-${serviceShort}' - virtualWanId: nestedDependencies.outputs.virtualWWANResourceId - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - tags: { - 'hidden-title': 'This is visible in the resource name' - tagA: 'valueA' - tagB: 'valueB' - } - deviceProperties: { - linkSpeedInMbps: 0 - } - vpnSiteLinks: [ - { - name: '${namePrefix}-vSite-${serviceShort}' - properties: { - bgpProperties: { - asn: 65010 - bgpPeeringAddress: '1.1.1.1' - } - ipAddress: '1.2.3.4' - linkProperties: { - linkProviderName: 'contoso' - linkSpeedInMbps: 5 - } - } +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}-${serviceShort}' + virtualWanId: nestedDependencies.outputs.virtualWWANResourceId + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + tags: { + 'hidden-title': 'This is visible in the resource name' + tagA: 'valueA' + tagB: 'valueB' } - { - name: 'Link1' - properties: { - bgpProperties: { - asn: 65020 - bgpPeeringAddress: '192.168.1.0' + deviceProperties: { + linkSpeedInMbps: 0 + } + vpnSiteLinks: [ + { + name: '${namePrefix}-vSite-${serviceShort}' + properties: { + bgpProperties: { + asn: 65010 + bgpPeeringAddress: '1.1.1.1' + } + ipAddress: '1.2.3.4' + linkProperties: { + linkProviderName: 'contoso' + linkSpeedInMbps: 5 + } } - ipAddress: '2.2.2.2' - linkProperties: { - linkProviderName: 'contoso' - linkSpeedInMbps: 5 + } + { + name: 'Link1' + properties: { + bgpProperties: { + asn: 65020 + bgpPeeringAddress: '192.168.1.0' + } + ipAddress: '2.2.2.2' + linkProperties: { + linkProviderName: 'contoso' + linkSpeedInMbps: 5 + } } } - } - ] - o365Policy: { - breakOutCategories: { - optimize: true - allow: true - default: true + ] + o365Policy: { + breakOutCategories: { + optimize: true + allow: true + default: true + } } } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/operational-insights/workspace/data-export/main.json b/avm/res/operational-insights/workspace/data-export/main.json index 950108de7f..740f371a8c 100644 --- a/avm/res/operational-insights/workspace/data-export/main.json +++ b/avm/res/operational-insights/workspace/data-export/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "12543023571728523937" + "version": "0.26.54.24096", + "templateHash": "5632716318105950604" }, "name": "Log Analytics Workspace Data Exports", "description": "This module deploys a Log Analytics Workspace Data Export.", diff --git a/avm/res/operational-insights/workspace/data-source/main.bicep b/avm/res/operational-insights/workspace/data-source/main.bicep index 64fc1b3371..905ff55e0e 100644 --- a/avm/res/operational-insights/workspace/data-source/main.bicep +++ b/avm/res/operational-insights/workspace/data-source/main.bicep @@ -70,13 +70,23 @@ resource dataSource 'Microsoft.OperationalInsights/workspaces/dataSources@2020-0 linkedResourceId: !empty(kind) && kind == 'AzureActivityLog' ? linkedResourceId : null eventLogName: !empty(kind) && kind == 'WindowsEvent' ? eventLogName : null eventTypes: !empty(kind) && kind == 'WindowsEvent' ? eventTypes : null - objectName: !empty(kind) && (kind == 'WindowsPerformanceCounter' || kind == 'LinuxPerformanceObject') ? objectName : null - instanceName: !empty(kind) && (kind == 'WindowsPerformanceCounter' || kind == 'LinuxPerformanceObject') ? instanceName : null - intervalSeconds: !empty(kind) && (kind == 'WindowsPerformanceCounter' || kind == 'LinuxPerformanceObject') ? intervalSeconds : null + objectName: !empty(kind) && (kind == 'WindowsPerformanceCounter' || kind == 'LinuxPerformanceObject') + ? objectName + : null + instanceName: !empty(kind) && (kind == 'WindowsPerformanceCounter' || kind == 'LinuxPerformanceObject') + ? instanceName + : null + intervalSeconds: !empty(kind) && (kind == 'WindowsPerformanceCounter' || kind == 'LinuxPerformanceObject') + ? intervalSeconds + : null counterName: !empty(kind) && kind == 'WindowsPerformanceCounter' ? counterName : null - state: !empty(kind) && (kind == 'IISLogs' || kind == 'LinuxSyslogCollection' || kind == 'LinuxPerformanceCollection') ? state : null + state: !empty(kind) && (kind == 'IISLogs' || kind == 'LinuxSyslogCollection' || kind == 'LinuxPerformanceCollection') + ? state + : null syslogName: !empty(kind) && kind == 'LinuxSyslog' ? syslogName : null - syslogSeverities: !empty(kind) && (kind == 'LinuxSyslog' || kind == 'LinuxPerformanceObject') ? syslogSeverities : null + syslogSeverities: !empty(kind) && (kind == 'LinuxSyslog' || kind == 'LinuxPerformanceObject') + ? syslogSeverities + : null performanceCounters: !empty(kind) && kind == 'LinuxPerformanceObject' ? performanceCounters : null } } diff --git a/avm/res/operational-insights/workspace/data-source/main.json b/avm/res/operational-insights/workspace/data-source/main.json index d77dd6f3af..53bded2d65 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.25.53.49325", - "templateHash": "14032975851567807564" + "version": "0.26.54.24096", + "templateHash": "16469989668419642499" }, "name": "Log Analytics Workspace Datasources", "description": "This module deploys a Log Analytics Workspace Data Source.", diff --git a/avm/res/operational-insights/workspace/linked-service/main.json b/avm/res/operational-insights/workspace/linked-service/main.json index 816832ad7c..1ce0ba554a 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.25.53.49325", - "templateHash": "14301767156435143002" + "version": "0.26.54.24096", + "templateHash": "7204307644126778192" }, "name": "Log Analytics Workspace Linked Services", "description": "This module deploys a Log Analytics Workspace Linked Service.", 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 701593c238..faf6726913 100644 --- a/avm/res/operational-insights/workspace/linked-storage-account/main.json +++ b/avm/res/operational-insights/workspace/linked-storage-account/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "6713282874166856483" + "version": "0.26.54.24096", + "templateHash": "8359295346488843789" }, "name": "Log Analytics Workspace Linked Storage Accounts", "description": "This module deploys a Log Analytics Workspace Linked Storage Account.", diff --git a/avm/res/operational-insights/workspace/main.bicep b/avm/res/operational-insights/workspace/main.bicep index 79621f30ce..37603b1ef1 100644 --- a/avm/res/operational-insights/workspace/main.bicep +++ b/avm/res/operational-insights/workspace/main.bicep @@ -97,44 +97,77 @@ param tags object? @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -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) ? 'SystemAssigned' : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : 'None') - userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null -} : null +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) + ? 'SystemAssigned' + : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : 'None') + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null + } + : null var 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') + '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 (Preview)': 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') + 'Role Based Access Control Administrator (Preview)': 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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.operationalinsights-workspace.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.operationalinsights-workspace.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = { location: location @@ -160,156 +193,187 @@ resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10 identity: identity } -resource logAnalyticsWorkspace_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource logAnalyticsWorkspace_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: logAnalyticsWorkspace } - scope: logAnalyticsWorkspace -}] - -module logAnalyticsWorkspace_storageInsightConfigs 'storage-insight-config/main.bicep' = [for (storageInsightsConfig, index) in storageInsightsConfigs: { - name: '${uniqueString(deployment().name, location)}-LAW-StorageInsightsConfig-${index}' - params: { - logAnalyticsWorkspaceName: logAnalyticsWorkspace.name - containers: contains(storageInsightsConfig, 'containers') ? storageInsightsConfig.containers : [] - tables: contains(storageInsightsConfig, 'tables') ? storageInsightsConfig.tables : [] - storageAccountResourceId: storageInsightsConfig.storageAccountResourceId +] + +module logAnalyticsWorkspace_storageInsightConfigs 'storage-insight-config/main.bicep' = [ + for (storageInsightsConfig, index) in storageInsightsConfigs: { + name: '${uniqueString(deployment().name, location)}-LAW-StorageInsightsConfig-${index}' + params: { + logAnalyticsWorkspaceName: logAnalyticsWorkspace.name + containers: contains(storageInsightsConfig, 'containers') ? storageInsightsConfig.containers : [] + tables: contains(storageInsightsConfig, 'tables') ? storageInsightsConfig.tables : [] + storageAccountResourceId: storageInsightsConfig.storageAccountResourceId + } } -}] - -module logAnalyticsWorkspace_linkedServices 'linked-service/main.bicep' = [for (linkedService, index) in linkedServices: { - name: '${uniqueString(deployment().name, location)}-LAW-LinkedService-${index}' - params: { - logAnalyticsWorkspaceName: logAnalyticsWorkspace.name - name: linkedService.name - resourceId: contains(linkedService, 'resourceId') ? linkedService.resourceId : '' - writeAccessResourceId: contains(linkedService, 'writeAccessResourceId') ? linkedService.writeAccessResourceId : '' +] + +module logAnalyticsWorkspace_linkedServices 'linked-service/main.bicep' = [ + for (linkedService, index) in linkedServices: { + name: '${uniqueString(deployment().name, location)}-LAW-LinkedService-${index}' + params: { + logAnalyticsWorkspaceName: logAnalyticsWorkspace.name + name: linkedService.name + resourceId: contains(linkedService, 'resourceId') ? linkedService.resourceId : '' + writeAccessResourceId: contains(linkedService, 'writeAccessResourceId') ? linkedService.writeAccessResourceId : '' + } } -}] - -module logAnalyticsWorkspace_linkedStorageAccounts 'linked-storage-account/main.bicep' = [for (linkedStorageAccount, index) in linkedStorageAccounts: { - name: '${uniqueString(deployment().name, location)}-LAW-LinkedStorageAccount-${index}' - params: { - logAnalyticsWorkspaceName: logAnalyticsWorkspace.name - name: linkedStorageAccount.name - resourceId: linkedStorageAccount.resourceId +] + +module logAnalyticsWorkspace_linkedStorageAccounts 'linked-storage-account/main.bicep' = [ + for (linkedStorageAccount, index) in linkedStorageAccounts: { + name: '${uniqueString(deployment().name, location)}-LAW-LinkedStorageAccount-${index}' + params: { + logAnalyticsWorkspaceName: logAnalyticsWorkspace.name + name: linkedStorageAccount.name + resourceId: linkedStorageAccount.resourceId + } } -}] - -module logAnalyticsWorkspace_savedSearches 'saved-search/main.bicep' = [for (savedSearch, index) in savedSearches: { - name: '${uniqueString(deployment().name, location)}-LAW-SavedSearch-${index}' - params: { - logAnalyticsWorkspaceName: logAnalyticsWorkspace.name - name: '${savedSearch.name}${uniqueString(deployment().name)}' - etag: savedSearch.?etag - displayName: savedSearch.displayName - category: savedSearch.category - query: savedSearch.query - functionAlias: savedSearch.?functionAlias - functionParameters: savedSearch.?functionParameters - version: savedSearch.?version +] + +module logAnalyticsWorkspace_savedSearches 'saved-search/main.bicep' = [ + for (savedSearch, index) in savedSearches: { + name: '${uniqueString(deployment().name, location)}-LAW-SavedSearch-${index}' + params: { + logAnalyticsWorkspaceName: logAnalyticsWorkspace.name + name: '${savedSearch.name}${uniqueString(deployment().name)}' + etag: savedSearch.?etag + displayName: savedSearch.displayName + category: savedSearch.category + query: savedSearch.query + functionAlias: savedSearch.?functionAlias + functionParameters: savedSearch.?functionParameters + version: savedSearch.?version + } + dependsOn: [ + logAnalyticsWorkspace_linkedStorageAccounts + ] } - dependsOn: [ - logAnalyticsWorkspace_linkedStorageAccounts - ] -}] - -module logAnalyticsWorkspace_dataExports 'data-export/main.bicep' = [for (dataExport, index) in dataExports: { - name: '${uniqueString(deployment().name, location)}-LAW-DataExport-${index}' - params: { - workspaceName: logAnalyticsWorkspace.name - name: dataExport.name - destination: contains(dataExport, 'destination') ? dataExport.destination : {} - enable: contains(dataExport, 'enable') ? dataExport.enable : false - tableNames: contains(dataExport, 'tableNames') ? dataExport.tableNames : [] +] + +module logAnalyticsWorkspace_dataExports 'data-export/main.bicep' = [ + for (dataExport, index) in dataExports: { + name: '${uniqueString(deployment().name, location)}-LAW-DataExport-${index}' + params: { + workspaceName: logAnalyticsWorkspace.name + name: dataExport.name + destination: contains(dataExport, 'destination') ? dataExport.destination : {} + enable: contains(dataExport, 'enable') ? dataExport.enable : false + tableNames: contains(dataExport, 'tableNames') ? dataExport.tableNames : [] + } } -}] - -module logAnalyticsWorkspace_dataSources 'data-source/main.bicep' = [for (dataSource, index) in dataSources: { - name: '${uniqueString(deployment().name, location)}-LAW-DataSource-${index}' - params: { - logAnalyticsWorkspaceName: logAnalyticsWorkspace.name - name: dataSource.name - kind: dataSource.kind - linkedResourceId: contains(dataSource, 'linkedResourceId') ? dataSource.linkedResourceId : '' - eventLogName: contains(dataSource, 'eventLogName') ? dataSource.eventLogName : '' - eventTypes: contains(dataSource, 'eventTypes') ? dataSource.eventTypes : [] - objectName: contains(dataSource, 'objectName') ? dataSource.objectName : '' - instanceName: contains(dataSource, 'instanceName') ? dataSource.instanceName : '' - intervalSeconds: contains(dataSource, 'intervalSeconds') ? dataSource.intervalSeconds : 60 - counterName: contains(dataSource, 'counterName') ? dataSource.counterName : '' - state: contains(dataSource, 'state') ? dataSource.state : '' - syslogName: contains(dataSource, 'syslogName') ? dataSource.syslogName : '' - syslogSeverities: contains(dataSource, 'syslogSeverities') ? dataSource.syslogSeverities : [] - performanceCounters: contains(dataSource, 'performanceCounters') ? dataSource.performanceCounters : [] +] + +module logAnalyticsWorkspace_dataSources 'data-source/main.bicep' = [ + for (dataSource, index) in dataSources: { + name: '${uniqueString(deployment().name, location)}-LAW-DataSource-${index}' + params: { + logAnalyticsWorkspaceName: logAnalyticsWorkspace.name + name: dataSource.name + kind: dataSource.kind + linkedResourceId: contains(dataSource, 'linkedResourceId') ? dataSource.linkedResourceId : '' + eventLogName: contains(dataSource, 'eventLogName') ? dataSource.eventLogName : '' + eventTypes: contains(dataSource, 'eventTypes') ? dataSource.eventTypes : [] + objectName: contains(dataSource, 'objectName') ? dataSource.objectName : '' + instanceName: contains(dataSource, 'instanceName') ? dataSource.instanceName : '' + intervalSeconds: contains(dataSource, 'intervalSeconds') ? dataSource.intervalSeconds : 60 + counterName: contains(dataSource, 'counterName') ? dataSource.counterName : '' + state: contains(dataSource, 'state') ? dataSource.state : '' + syslogName: contains(dataSource, 'syslogName') ? dataSource.syslogName : '' + syslogSeverities: contains(dataSource, 'syslogSeverities') ? dataSource.syslogSeverities : [] + performanceCounters: contains(dataSource, 'performanceCounters') ? dataSource.performanceCounters : [] + } } -}] - -module logAnalyticsWorkspace_tables 'table/main.bicep' = [for (table, index) in tables: { - name: '${uniqueString(deployment().name, location)}-LAW-Table-${index}' - params: { - workspaceName: logAnalyticsWorkspace.name - name: table.name - plan: table.?plan - schema: table.?schema - retentionInDays: table.?retentionInDays - totalRetentionInDays: table.?totalRetentionInDays - restoredLogs: table.?restoredLogs - searchResults: table.?searchResults - roleAssignments: table.?roleAssignments +] + +module logAnalyticsWorkspace_tables 'table/main.bicep' = [ + for (table, index) in tables: { + name: '${uniqueString(deployment().name, location)}-LAW-Table-${index}' + params: { + workspaceName: logAnalyticsWorkspace.name + name: table.name + plan: table.?plan + schema: table.?schema + retentionInDays: table.?retentionInDays + totalRetentionInDays: table.?totalRetentionInDays + restoredLogs: table.?restoredLogs + searchResults: table.?searchResults + roleAssignments: table.?roleAssignments + } } -}] - -module logAnalyticsWorkspace_solutions 'br/public:avm/res/operations-management/solution:0.1.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: contains(gallerySolution, 'product') ? gallerySolution.product : 'OMSGallery' - publisher: contains(gallerySolution, 'publisher') ? gallerySolution.publisher : 'Microsoft' - enableTelemetry: gallerySolution.?enableTelemetry ?? enableTelemetry +] + +module logAnalyticsWorkspace_solutions 'br/public:avm/res/operations-management/solution:0.1.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: contains(gallerySolution, 'product') ? gallerySolution.product : 'OMSGallery' + publisher: contains(gallerySolution, 'publisher') ? gallerySolution.publisher : 'Microsoft' + enableTelemetry: gallerySolution.?enableTelemetry ?? enableTelemetry + } } -}] - -resource logAnalyticsWorkspace_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.' +] + +resource logAnalyticsWorkspace_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: logAnalyticsWorkspace } - scope: logAnalyticsWorkspace -} -resource logAnalyticsWorkspace_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(logAnalyticsWorkspace.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource logAnalyticsWorkspace_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(logAnalyticsWorkspace.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: logAnalyticsWorkspace } - scope: logAnalyticsWorkspace -}] +] @description('The resource ID of the deployed log analytics workspace.') output resourceId string = logAnalyticsWorkspace.id diff --git a/avm/res/operational-insights/workspace/main.json b/avm/res/operational-insights/workspace/main.json index 3b5d442bbf..fc85a91285 100644 --- a/avm/res/operational-insights/workspace/main.json +++ b/avm/res/operational-insights/workspace/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "13719053295620709128" + "version": "0.26.54.24096", + "templateHash": "12748269165141825812" }, "name": "Log Analytics Workspaces", "description": "This module deploys a Log Analytics Workspace.", @@ -606,8 +606,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4862843187650272248" + "version": "0.26.54.24096", + "templateHash": "8017888514977253474" }, "name": "Log Analytics Workspace Storage Insight Configs", "description": "This module deploys a Log Analytics Workspace Storage Insight Config.", @@ -746,8 +746,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14301767156435143002" + "version": "0.26.54.24096", + "templateHash": "7204307644126778192" }, "name": "Log Analytics Workspace Linked Services", "description": "This module deploys a Log Analytics Workspace Linked Service.", @@ -868,8 +868,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "6713282874166856483" + "version": "0.26.54.24096", + "templateHash": "8359295346488843789" }, "name": "Log Analytics Workspace Linked Storage Accounts", "description": "This module deploys a Log Analytics Workspace Linked Storage Account.", @@ -991,8 +991,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17950009471823327560" + "version": "0.26.54.24096", + "templateHash": "1713932205136149020" }, "name": "Log Analytics Workspace Saved Searches", "description": "This module deploys a Log Analytics Workspace Saved Search.", @@ -1151,8 +1151,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "12543023571728523937" + "version": "0.26.54.24096", + "templateHash": "5632716318105950604" }, "name": "Log Analytics Workspace Data Exports", "description": "This module deploys a Log Analytics Workspace Data Export.", @@ -1278,8 +1278,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14032975851567807564" + "version": "0.26.54.24096", + "templateHash": "16469989668419642499" }, "name": "Log Analytics Workspace Datasources", "description": "This module deploys a Log Analytics Workspace Data Source.", @@ -1509,8 +1509,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4932423807790181892" + "version": "0.26.54.24096", + "templateHash": "5509602447929603635" }, "name": "Log Analytics Workspace Tables", "description": "This module deploys a Log Analytics Workspace Table.", diff --git a/avm/res/operational-insights/workspace/saved-search/main.json b/avm/res/operational-insights/workspace/saved-search/main.json index 1c32337b14..2c0198f9cf 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.25.53.49325", - "templateHash": "17950009471823327560" + "version": "0.26.54.24096", + "templateHash": "1713932205136149020" }, "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/main.json b/avm/res/operational-insights/workspace/storage-insight-config/main.json index fa8367fe5c..8c7e403d99 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.25.53.49325", - "templateHash": "4862843187650272248" + "version": "0.26.54.24096", + "templateHash": "8017888514977253474" }, "name": "Log Analytics Workspace Storage Insight Configs", "description": "This module deploys a Log Analytics Workspace Storage Insight Config.", diff --git a/avm/res/operational-insights/workspace/table/main.bicep b/avm/res/operational-insights/workspace/table/main.bicep index e0df3b94f4..3bbbc6f38b 100644 --- a/avm/res/operational-insights/workspace/table/main.bicep +++ b/avm/res/operational-insights/workspace/table/main.bicep @@ -43,14 +43,32 @@ param roleAssignments roleAssignmentType var 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') + '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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } // =============== // @@ -74,19 +92,25 @@ resource table 'Microsoft.OperationalInsights/workspaces/tables@2022-10-01' = { } } -resource table_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(table.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource table_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(table.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: table } - scope: table -}] +] // =========== // // Outputs // diff --git a/avm/res/operational-insights/workspace/table/main.json b/avm/res/operational-insights/workspace/table/main.json index 94607473ef..2b283e3b8e 100644 --- a/avm/res/operational-insights/workspace/table/main.json +++ b/avm/res/operational-insights/workspace/table/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4932423807790181892" + "version": "0.26.54.24096", + "templateHash": "5509602447929603635" }, "name": "Log Analytics Workspace Tables", "description": "This module deploys a Log Analytics Workspace Table.", 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 26a40f0653..8bfaf20aee 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 @@ -63,283 +63,291 @@ 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 - dailyQuotaGb: 10 - dataSources: [ - { - eventLogName: 'Application' - eventTypes: [ - { - eventType: 'Error' - } - { - eventType: 'Warning' - } - { - eventType: 'Information' - } - ] - kind: 'WindowsEvent' - name: 'applicationEvent' - } - { - counterName: '% Processor Time' - instanceName: '*' - intervalSeconds: 60 - kind: 'WindowsPerformanceCounter' - name: 'windowsPerfCounter1' - objectName: 'Processor' - } - { - kind: 'IISLogs' - name: 'sampleIISLog1' - state: 'OnPremiseEnabled' - } - { - kind: 'LinuxSyslog' - name: 'sampleSyslog1' - syslogName: 'kern' - syslogSeverities: [ - { - severity: 'emerg' - } - { - severity: 'alert' - } - { - severity: 'crit' - } - { - severity: 'err' - } - { - severity: 'warning' - } - ] - } - { - kind: 'LinuxSyslogCollection' - name: 'sampleSyslogCollection1' - state: 'Enabled' - } - { - instanceName: '*' - intervalSeconds: 10 - kind: 'LinuxPerformanceObject' - name: 'sampleLinuxPerf1' - objectName: 'Logical Disk' - syslogSeverities: [ - { - counterName: '% Used Inodes' - } - { - counterName: 'Free Megabytes' - } - { - counterName: '% Used Space' - } - { - counterName: 'Disk Transfers/sec' - } - { - counterName: 'Disk Reads/sec' - } - { - counterName: 'Disk Writes/sec' - } - ] - } - { - kind: 'LinuxPerformanceCollection' - name: 'sampleLinuxPerfCollection1' - state: 'Enabled' - } - ] - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - gallerySolutions: [ - { - name: 'AzureAutomation' - product: 'OMSGallery' - publisher: 'Microsoft' - } - ] - linkedServices: [ - { - name: 'Automation' - resourceId: nestedDependencies.outputs.automationAccountResourceId - } - ] - linkedStorageAccounts: [ - { - name: 'Query' - resourceId: nestedDependencies.outputs.storageAccountResourceId - } - ] - publicNetworkAccessForIngestion: 'Disabled' - publicNetworkAccessForQuery: 'Disabled' - savedSearches: [ - { - category: 'VDC Saved Searches' - displayName: 'VMSS Instance Count2' - name: 'VMSSQueries' - query: 'Event | where Source == ServiceFabricNodeBootstrapAgent | summarize AggregatedValue = count() by Computer' - } - ] - storageInsightsConfigs: [ - { - storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId - tables: [ - 'LinuxsyslogVer2v0' - 'WADETWEventTable' - 'WADServiceFabric*EventTable' - 'WADWindowsEventLogsTable' - ] - } - ] - useResourcePermissions: true - tables: [ - { - name: 'CustomTableBasic_CL' - schema: { - name: 'CustomTableBasic_CL' - columns: [ +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 + dailyQuotaGb: 10 + dataSources: [ + { + eventLogName: 'Application' + eventTypes: [ + { + eventType: 'Error' + } { - name: 'TimeGenerated' - type: 'DateTime' + eventType: 'Warning' } { - name: 'RawData' - type: 'String' + eventType: 'Information' } ] + kind: 'WindowsEvent' + name: 'applicationEvent' } - totalRetentionInDays: 90 - retentionInDays: 60 - 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' - } - ] - } - { - name: 'CustomTableAdvanced_CL' - schema: { - name: 'CustomTableAdvanced_CL' - columns: [ + { + counterName: '% Processor Time' + instanceName: '*' + intervalSeconds: 60 + kind: 'WindowsPerformanceCounter' + name: 'windowsPerfCounter1' + objectName: 'Processor' + } + { + kind: 'IISLogs' + name: 'sampleIISLog1' + state: 'OnPremiseEnabled' + } + { + kind: 'LinuxSyslog' + name: 'sampleSyslog1' + syslogName: 'kern' + syslogSeverities: [ + { + severity: 'emerg' + } + { + severity: 'alert' + } + { + severity: 'crit' + } { - name: 'TimeGenerated' - type: 'DateTime' + severity: 'err' } { - name: 'EventTime' - type: 'DateTime' + severity: 'warning' + } + ] + } + { + kind: 'LinuxSyslogCollection' + name: 'sampleSyslogCollection1' + state: 'Enabled' + } + { + instanceName: '*' + intervalSeconds: 10 + kind: 'LinuxPerformanceObject' + name: 'sampleLinuxPerf1' + objectName: 'Logical Disk' + syslogSeverities: [ + { + counterName: '% Used Inodes' + } + { + counterName: 'Free Megabytes' } { - name: 'EventLevel' - type: 'String' + counterName: '% Used Space' } { - name: 'EventCode' - type: 'Int' + counterName: 'Disk Transfers/sec' } { - name: 'Message' - type: 'String' + counterName: 'Disk Reads/sec' } { - name: 'RawData' - type: 'String' + counterName: 'Disk Writes/sec' } ] } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + { + kind: 'LinuxPerformanceCollection' + name: 'sampleLinuxPerfCollection1' + state: 'Enabled' + } + ] + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + gallerySolutions: [ + { + name: 'AzureAutomation' + product: 'OMSGallery' + publisher: 'Microsoft' + } + ] + linkedServices: [ + { + name: 'Automation' + resourceId: nestedDependencies.outputs.automationAccountResourceId + } + ] + linkedStorageAccounts: [ + { + name: 'Query' + resourceId: nestedDependencies.outputs.storageAccountResourceId + } + ] + publicNetworkAccessForIngestion: 'Disabled' + publicNetworkAccessForQuery: 'Disabled' + savedSearches: [ + { + category: 'VDC Saved Searches' + displayName: 'VMSS Instance Count2' + name: 'VMSSQueries' + query: 'Event | where Source == ServiceFabricNodeBootstrapAgent | summarize AggregatedValue = count() by Computer' + } + ] + storageInsightsConfigs: [ + { + storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + tables: [ + 'LinuxsyslogVer2v0' + 'WADETWEventTable' + 'WADServiceFabric*EventTable' + 'WADWindowsEventLogsTable' + ] + } + ] + useResourcePermissions: true + tables: [ + { + name: 'CustomTableBasic_CL' + schema: { + name: 'CustomTableBasic_CL' + columns: [ + { + name: 'TimeGenerated' + type: 'DateTime' + } + { + name: 'RawData' + type: 'String' + } + ] } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + totalRetentionInDays: 90 + retentionInDays: 60 + 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' + } + ] + } + { + name: 'CustomTableAdvanced_CL' + schema: { + name: 'CustomTableAdvanced_CL' + columns: [ + { + name: 'TimeGenerated' + type: 'DateTime' + } + { + name: 'EventTime' + type: 'DateTime' + } + { + name: 'EventLevel' + type: 'String' + } + { + name: 'EventCode' + type: 'Int' + } + { + name: 'Message' + type: 'String' + } + { + name: 'RawData' + type: 'String' + } + ] } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + 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' + } + ] + } + ] + dataExports: [ + { + name: 'eventHubExport' + enable: true + destination: { + resourceId: nestedDependencies.outputs.eventHubNamespaceResourceId + metaData: { + eventHubName: nestedDependencies.outputs.eventHubName + } } - ] - } - ] - dataExports: [ - { - name: 'eventHubExport' - enable: true - destination: { - resourceId: nestedDependencies.outputs.eventHubNamespaceResourceId - metaData: { - eventHubName: nestedDependencies.outputs.eventHubName + tableNames: [ + 'Alert' + 'InsightsMetrics' + ] + } + { + name: 'storageAccountExport' + enable: true + destination: { + resourceId: nestedDependencies.outputs.storageAccountResourceId } + tableNames: [ + 'Operation' + ] } - tableNames: [ - 'Alert' - 'InsightsMetrics' + ] + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId ] } - { - name: 'storageAccountExport' - enable: true - destination: { - resourceId: nestedDependencies.outputs.storageAccountResourceId - } - tableNames: [ - 'Operation' - ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - managedIdentities: { - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/operational-insights/workspace/tests/e2e/defaults/main.test.bicep b/avm/res/operational-insights/workspace/tests/e2e/defaults/main.test.bicep index 1239251a63..be86d0d2e5 100644 --- a/avm/res/operational-insights/workspace/tests/e2e/defaults/main.test.bicep +++ b/avm/res/operational-insights/workspace/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { // ============== // @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 +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 + } } -}] +] 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 c294bdd177..6de957e29f 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 @@ -61,286 +61,297 @@ 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 - dailyQuotaGb: 10 - dataSources: [ - { - eventLogName: 'Application' - eventTypes: [ - { - eventType: 'Error' - } - { - eventType: 'Warning' - } - { - eventType: 'Information' - } - ] - kind: 'WindowsEvent' - name: 'applicationEvent' - } - { - counterName: '% Processor Time' - instanceName: '*' - intervalSeconds: 60 - kind: 'WindowsPerformanceCounter' - name: 'windowsPerfCounter1' - objectName: 'Processor' - } - { - kind: 'IISLogs' - name: 'sampleIISLog1' - state: 'OnPremiseEnabled' - } - { - kind: 'LinuxSyslog' - name: 'sampleSyslog1' - syslogName: 'kern' - syslogSeverities: [ - { - severity: 'emerg' - } - { - severity: 'alert' - } - { - severity: 'crit' - } - { - severity: 'err' - } - { - severity: 'warning' - } - ] - } - { - kind: 'LinuxSyslogCollection' - name: 'sampleSyslogCollection1' - state: 'Enabled' - } - { - instanceName: '*' - intervalSeconds: 10 - kind: 'LinuxPerformanceObject' - name: 'sampleLinuxPerf1' - objectName: 'Logical Disk' - syslogSeverities: [ - { - counterName: '% Used Inodes' - } - { - counterName: 'Free Megabytes' - } - { - counterName: '% Used Space' - } - { - counterName: 'Disk Transfers/sec' - } - { - counterName: 'Disk Reads/sec' - } - { - counterName: 'Disk Writes/sec' - } - ] - } - { - kind: 'LinuxPerformanceCollection' - name: 'sampleLinuxPerfCollection1' - state: 'Enabled' - } - ] - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - gallerySolutions: [ - { - name: 'AzureAutomation' - product: 'OMSGallery' - publisher: 'Microsoft' - } - ] - linkedServices: [ - { - name: 'Automation' - resourceId: nestedDependencies.outputs.automationAccountResourceId - } - ] - linkedStorageAccounts: [ - { - name: 'Query' - resourceId: nestedDependencies.outputs.storageAccountResourceId - } - ] - tables: [ - { - name: 'CustomTableBasic_CL' - schema: { - name: 'CustomTableBasic_CL' - columns: [ +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 + dailyQuotaGb: 10 + dataSources: [ + { + eventLogName: 'Application' + eventTypes: [ + { + eventType: 'Error' + } { - name: 'TimeGenerated' - type: 'DateTime' + eventType: 'Warning' } { - name: 'RawData' - type: 'String' + eventType: 'Information' } ] + kind: 'WindowsEvent' + name: 'applicationEvent' } - totalRetentionInDays: 90 - retentionInDays: 60 - 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' - } - ] - } - { - name: 'CustomTableAdvanced_CL' - schema: { - name: 'CustomTableAdvanced_CL' - columns: [ + { + counterName: '% Processor Time' + instanceName: '*' + intervalSeconds: 60 + kind: 'WindowsPerformanceCounter' + name: 'windowsPerfCounter1' + objectName: 'Processor' + } + { + kind: 'IISLogs' + name: 'sampleIISLog1' + state: 'OnPremiseEnabled' + } + { + kind: 'LinuxSyslog' + name: 'sampleSyslog1' + syslogName: 'kern' + syslogSeverities: [ { - name: 'TimeGenerated' - type: 'DateTime' + severity: 'emerg' } { - name: 'EventTime' - type: 'DateTime' + severity: 'alert' } { - name: 'EventLevel' - type: 'String' + severity: 'crit' + } + { + severity: 'err' + } + { + severity: 'warning' + } + ] + } + { + kind: 'LinuxSyslogCollection' + name: 'sampleSyslogCollection1' + state: 'Enabled' + } + { + instanceName: '*' + intervalSeconds: 10 + kind: 'LinuxPerformanceObject' + name: 'sampleLinuxPerf1' + objectName: 'Logical Disk' + syslogSeverities: [ + { + counterName: '% Used Inodes' } { - name: 'EventCode' - type: 'Int' + counterName: 'Free Megabytes' } { - name: 'Message' - type: 'String' + counterName: '% Used Space' } { - name: 'RawData' - type: 'String' + counterName: 'Disk Transfers/sec' + } + { + counterName: 'Disk Reads/sec' + } + { + counterName: 'Disk Writes/sec' } ] } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + { + kind: 'LinuxPerformanceCollection' + name: 'sampleLinuxPerfCollection1' + state: 'Enabled' + } + ] + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + gallerySolutions: [ + { + name: 'AzureAutomation' + product: 'OMSGallery' + publisher: 'Microsoft' + } + ] + linkedServices: [ + { + name: 'Automation' + resourceId: nestedDependencies.outputs.automationAccountResourceId + } + ] + linkedStorageAccounts: [ + { + name: 'Query' + resourceId: nestedDependencies.outputs.storageAccountResourceId + } + ] + tables: [ + { + name: 'CustomTableBasic_CL' + schema: { + name: 'CustomTableBasic_CL' + columns: [ + { + name: 'TimeGenerated' + type: 'DateTime' + } + { + name: 'RawData' + type: 'String' + } + ] } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + totalRetentionInDays: 90 + retentionInDays: 60 + 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' + } + ] + } + { + name: 'CustomTableAdvanced_CL' + schema: { + name: 'CustomTableAdvanced_CL' + columns: [ + { + name: 'TimeGenerated' + type: 'DateTime' + } + { + name: 'EventTime' + type: 'DateTime' + } + { + name: 'EventLevel' + type: 'String' + } + { + name: 'EventCode' + type: 'Int' + } + { + name: 'Message' + type: 'String' + } + { + name: 'RawData' + type: 'String' + } + ] } - ] + 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' + } + ] + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - publicNetworkAccessForIngestion: 'Disabled' - publicNetworkAccessForQuery: 'Disabled' - savedSearches: [ - { - category: 'VDC Saved Searches' - displayName: 'VMSS Instance Count2' - name: 'VMSSQueries' - query: 'Event | where Source == ServiceFabricNodeBootstrapAgent | summarize AggregatedValue = count() by Computer' - tags: [ - { - Name: 'Environment' - Value: 'Non-Prod' - } - { - Name: 'Role' - Value: 'DeploymentValidation' - } - ] + publicNetworkAccessForIngestion: 'Disabled' + publicNetworkAccessForQuery: 'Disabled' + savedSearches: [ + { + category: 'VDC Saved Searches' + displayName: 'VMSS Instance Count2' + name: 'VMSSQueries' + query: 'Event | where Source == ServiceFabricNodeBootstrapAgent | summarize AggregatedValue = count() by Computer' + tags: [ + { + Name: 'Environment' + Value: 'Non-Prod' + } + { + Name: 'Role' + Value: 'DeploymentValidation' + } + ] + } + ] + storageInsightsConfigs: [ + { + storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + tables: [ + 'LinuxsyslogVer2v0' + 'WADETWEventTable' + 'WADServiceFabric*EventTable' + 'WADWindowsEventLogsTable' + ] + } + ] + useResourcePermissions: true + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - storageInsightsConfigs: [ - { - storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId - tables: [ - 'LinuxsyslogVer2v0' - 'WADETWEventTable' - 'WADServiceFabric*EventTable' - 'WADWindowsEventLogsTable' - ] + managedIdentities: { + systemAssigned: true } - ] - useResourcePermissions: true - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - managedIdentities: { - systemAssigned: true + 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' + } + ] } - 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' - } + dependsOn: [ + nestedDependencies + diagnosticDependencies ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] 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 03149b975f..62e91d5492 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 @@ -60,155 +60,157 @@ 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 - dailyQuotaGb: 10 - dataSources: [ - { - eventLogName: 'Application' - eventTypes: [ - { - eventType: 'Error' - } - { - eventType: 'Warning' - } - { - eventType: 'Information' - } - ] - kind: 'WindowsEvent' - name: 'applicationEvent' - } - { - counterName: '% Processor Time' - instanceName: '*' - intervalSeconds: 60 - kind: 'WindowsPerformanceCounter' - name: 'windowsPerfCounter1' - objectName: 'Processor' - } - { - kind: 'IISLogs' - name: 'sampleIISLog1' - state: 'OnPremiseEnabled' - } - { - kind: 'LinuxSyslog' - name: 'sampleSyslog1' - syslogName: 'kern' - syslogSeverities: [ - { - severity: 'emerg' - } - { - severity: 'alert' - } - { - severity: 'crit' - } - { - severity: 'err' - } - { - severity: 'warning' - } - ] +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 + dailyQuotaGb: 10 + dataSources: [ + { + eventLogName: 'Application' + eventTypes: [ + { + eventType: 'Error' + } + { + eventType: 'Warning' + } + { + eventType: 'Information' + } + ] + kind: 'WindowsEvent' + name: 'applicationEvent' + } + { + counterName: '% Processor Time' + instanceName: '*' + intervalSeconds: 60 + kind: 'WindowsPerformanceCounter' + name: 'windowsPerfCounter1' + objectName: 'Processor' + } + { + kind: 'IISLogs' + name: 'sampleIISLog1' + state: 'OnPremiseEnabled' + } + { + kind: 'LinuxSyslog' + name: 'sampleSyslog1' + syslogName: 'kern' + syslogSeverities: [ + { + severity: 'emerg' + } + { + severity: 'alert' + } + { + severity: 'crit' + } + { + severity: 'err' + } + { + severity: 'warning' + } + ] + } + { + kind: 'LinuxSyslogCollection' + name: 'sampleSyslogCollection1' + state: 'Enabled' + } + { + instanceName: '*' + intervalSeconds: 10 + kind: 'LinuxPerformanceObject' + name: 'sampleLinuxPerf1' + objectName: 'Logical Disk' + syslogSeverities: [ + { + counterName: '% Used Inodes' + } + { + counterName: 'Free Megabytes' + } + { + counterName: '% Used Space' + } + { + counterName: 'Disk Transfers/sec' + } + { + counterName: 'Disk Reads/sec' + } + { + counterName: 'Disk Writes/sec' + } + ] + } + { + kind: 'LinuxPerformanceCollection' + name: 'sampleLinuxPerfCollection1' + state: 'Enabled' + } + ] + diagnosticSettings: [ + { + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + gallerySolutions: [ + { + name: 'AzureAutomation' + product: 'OMSGallery' + publisher: 'Microsoft' + } + ] + linkedServices: [ + { + name: 'Automation' + resourceId: nestedDependencies.outputs.automationAccountResourceId + } + ] + linkedStorageAccounts: [ + { + name: 'Query' + resourceId: nestedDependencies.outputs.storageAccountResourceId + } + ] + publicNetworkAccessForIngestion: 'Disabled' + publicNetworkAccessForQuery: 'Disabled' + storageInsightsConfigs: [ + { + storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + tables: [ + 'LinuxsyslogVer2v0' + 'WADETWEventTable' + 'WADServiceFabric*EventTable' + 'WADWindowsEventLogsTable' + ] + } + ] + useResourcePermissions: true + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - { - kind: 'LinuxSyslogCollection' - name: 'sampleSyslogCollection1' - state: 'Enabled' + managedIdentities: { + systemAssigned: true } - { - instanceName: '*' - intervalSeconds: 10 - kind: 'LinuxPerformanceObject' - name: 'sampleLinuxPerf1' - objectName: 'Logical Disk' - syslogSeverities: [ - { - counterName: '% Used Inodes' - } - { - counterName: 'Free Megabytes' - } - { - counterName: '% Used Space' - } - { - counterName: 'Disk Transfers/sec' - } - { - counterName: 'Disk Reads/sec' - } - { - counterName: 'Disk Writes/sec' - } - ] - } - { - kind: 'LinuxPerformanceCollection' - name: 'sampleLinuxPerfCollection1' - state: 'Enabled' - } - ] - diagnosticSettings: [ - { - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - gallerySolutions: [ - { - name: 'AzureAutomation' - product: 'OMSGallery' - publisher: 'Microsoft' - } - ] - linkedServices: [ - { - name: 'Automation' - resourceId: nestedDependencies.outputs.automationAccountResourceId - } - ] - linkedStorageAccounts: [ - { - name: 'Query' - resourceId: nestedDependencies.outputs.storageAccountResourceId - } - ] - publicNetworkAccessForIngestion: 'Disabled' - publicNetworkAccessForQuery: 'Disabled' - storageInsightsConfigs: [ - { - storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId - tables: [ - 'LinuxsyslogVer2v0' - 'WADETWEventTable' - 'WADServiceFabric*EventTable' - 'WADWindowsEventLogsTable' - ] - } - ] - useResourcePermissions: true - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - managedIdentities: { - systemAssigned: true } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/operations-management/solution/main.bicep b/avm/res/operations-management/solution/main.bicep index 5b5a475ae2..ba755c0e30 100644 --- a/avm/res/operations-management/solution/main.bicep +++ b/avm/res/operations-management/solution/main.bicep @@ -20,23 +20,24 @@ param publisher string = 'Microsoft' @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.operationsmanagement-solution.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.operationsmanagement-solution.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' existing = { name: logAnalyticsWorkspaceName diff --git a/avm/res/operations-management/solution/main.json b/avm/res/operations-management/solution/main.json index 3edc6a4986..dce939ae5e 100644 --- a/avm/res/operations-management/solution/main.json +++ b/avm/res/operations-management/solution/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2322213504829983181" + "version": "0.26.54.24096", + "templateHash": "6056662833176375018" }, "name": "Operations Management Solutions", "description": "This module deploys an Operations Management Solution.", 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 5fa771d83f..606797373d 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 @@ -45,14 +45,16 @@ 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: 'AzureAutomation' - location: resourceLocation - logAnalyticsWorkspaceName: nestedDependencies.outputs.logAnalyticsWorkspaceName - product: 'OMSGallery' - publisher: 'Microsoft' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: 'AzureAutomation' + location: resourceLocation + logAnalyticsWorkspaceName: nestedDependencies.outputs.logAnalyticsWorkspaceName + product: 'OMSGallery' + publisher: 'Microsoft' + } } -}] +] diff --git a/avm/res/power-bi-dedicated/capacity/main.bicep b/avm/res/power-bi-dedicated/capacity/main.bicep index 0a007fd465..96139932db 100644 --- a/avm/res/power-bi-dedicated/capacity/main.bicep +++ b/avm/res/power-bi-dedicated/capacity/main.bicep @@ -35,31 +35,44 @@ param roleAssignments roleAssignmentType var 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') + 'Log Analytics Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '92aaf0da-9dab-42b6-94a3-d43ce8d16293' + ) + 'Log Analytics Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '73c42c96-874c-492b-b04d-ab87d138a893' + ) 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') + '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' + ) } -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableTelemetry) { - name: '46d3xbcp.res.powerbidedicated-capacity.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.powerbidedicated-capacity.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource capacity 'Microsoft.PowerBIDedicated/capacities@2021-01-01' = { name: name @@ -78,28 +91,37 @@ resource capacity 'Microsoft.PowerBIDedicated/capacities@2021-01-01' = { } } -resource capacity_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.' +resource capacity_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: capacity } - scope: capacity -} -resource capacity_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(capacity.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource capacity_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(capacity.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: capacity } - scope: capacity -}] +] @description('The resource ID of the PowerBi Embedded instance.') output resourceId string = capacity.id diff --git a/avm/res/power-bi-dedicated/capacity/main.json b/avm/res/power-bi-dedicated/capacity/main.json index d50d7153e0..e69dccfb92 100644 --- a/avm/res/power-bi-dedicated/capacity/main.json +++ b/avm/res/power-bi-dedicated/capacity/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "401112188619972880" + "version": "0.26.54.24096", + "templateHash": "6849452941887309833" }, "name": "Power BI Dedicated Capacities", "description": "This module deploys a Power BI Dedicated Capacity.", diff --git a/avm/res/power-bi-dedicated/capacity/tests/e2e/defaults/dependencies.bicep b/avm/res/power-bi-dedicated/capacity/tests/e2e/defaults/dependencies.bicep index a7f42aee7b..7be39e253a 100644 --- a/avm/res/power-bi-dedicated/capacity/tests/e2e/defaults/dependencies.bicep +++ b/avm/res/power-bi-dedicated/capacity/tests/e2e/defaults/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/power-bi-dedicated/capacity/tests/e2e/defaults/main.test.bicep b/avm/res/power-bi-dedicated/capacity/tests/e2e/defaults/main.test.bicep index db1935917b..515de7d0b9 100644 --- a/avm/res/power-bi-dedicated/capacity/tests/e2e/defaults/main.test.bicep +++ b/avm/res/power-bi-dedicated/capacity/tests/e2e/defaults/main.test.bicep @@ -45,17 +45,19 @@ 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' - sku: { - capacity: 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' + sku: { + capacity: 1 + } + members: [ + nestedDependencies.outputs.managedIdentityPrincipalId + ] + location: resourceLocation } - members: [ - nestedDependencies.outputs.managedIdentityPrincipalId - ] - location: resourceLocation } -}] +] diff --git a/avm/res/power-bi-dedicated/capacity/tests/e2e/max/dependencies.bicep b/avm/res/power-bi-dedicated/capacity/tests/e2e/max/dependencies.bicep index a7f42aee7b..7be39e253a 100644 --- a/avm/res/power-bi-dedicated/capacity/tests/e2e/max/dependencies.bicep +++ b/avm/res/power-bi-dedicated/capacity/tests/e2e/max/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/power-bi-dedicated/capacity/tests/e2e/max/main.test.bicep b/avm/res/power-bi-dedicated/capacity/tests/e2e/max/main.test.bicep index 2e6a779030..5284ba311d 100644 --- a/avm/res/power-bi-dedicated/capacity/tests/e2e/max/main.test.bicep +++ b/avm/res/power-bi-dedicated/capacity/tests/e2e/max/main.test.bicep @@ -45,46 +45,51 @@ 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 - sku: { - capacity: 1 - name: 'A1' - tier: 'PBIE_Azure' - } - mode: 'Gen2' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - members: [ - nestedDependencies.outputs.managedIdentityPrincipalId - ] - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +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 + sku: { + capacity: 1 + name: 'A1' + tier: 'PBIE_Azure' } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + mode: 'Gen2' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + members: [ + nestedDependencies.outputs.managedIdentityPrincipalId + ] + 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' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/power-bi-dedicated/capacity/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/power-bi-dedicated/capacity/tests/e2e/waf-aligned/dependencies.bicep index a7f42aee7b..7be39e253a 100644 --- a/avm/res/power-bi-dedicated/capacity/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/power-bi-dedicated/capacity/tests/e2e/waf-aligned/dependencies.bicep @@ -5,8 +5,8 @@ param location string = resourceGroup().location param managedIdentityName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } @description('The principal ID of the created Managed Identity.') diff --git a/avm/res/power-bi-dedicated/capacity/tests/e2e/waf-aligned/main.test.bicep b/avm/res/power-bi-dedicated/capacity/tests/e2e/waf-aligned/main.test.bicep index c412a4ef4a..06d353ab48 100644 --- a/avm/res/power-bi-dedicated/capacity/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/power-bi-dedicated/capacity/tests/e2e/waf-aligned/main.test.bicep @@ -45,26 +45,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 - sku: { - capacity: 1 - } - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - members: [ - nestedDependencies.outputs.managedIdentityPrincipalId - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +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 + sku: { + capacity: 1 + } + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + members: [ + nestedDependencies.outputs.managedIdentityPrincipalId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } } -}] +] diff --git a/avm/res/purview/account/main.bicep b/avm/res/purview/account/main.bicep index a62c667df3..dd883a0b37 100644 --- a/avm/res/purview/account/main.bicep +++ b/avm/res/purview/account/main.bicep @@ -58,7 +58,11 @@ param lock lockType // 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 formattedUserAssignedIdentities = reduce( + map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), + {}, + (cur, next) => union(cur, next) +) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } var identity = { type: !empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned' @@ -69,27 +73,34 @@ 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.purview-account.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.purview-account.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource account 'Microsoft.Purview/accounts@2021-07-01' = { name: name @@ -103,261 +114,326 @@ resource account 'Microsoft.Purview/accounts@2021-07-01' = { } } -resource account_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.' +resource account_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: account } - scope: account -} -resource account_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource account_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: account } - scope: account -}] - -module account_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.1' = [for (privateEndpoint, index) in (accountPrivateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-Account-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' - privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' - properties: { - privateLinkServiceId: account.id - groupIds: [ - privateEndpoint.?service ?? 'account' +] + +module account_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.1' = [ + for (privateEndpoint, index) in (accountPrivateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-Account-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' + properties: { + privateLinkServiceId: account.id + groupIds: [ + privateEndpoint.?service ?? 'account' + ] + } + } ] - } - } - ] : null - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' - properties: { - privateLinkServiceId: account.id - groupIds: [ - privateEndpoint.?service ?? 'account' + : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' + properties: { + privateLinkServiceId: account.id + groupIds: [ + privateEndpoint.?service ?? 'account' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] - -module portal_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.1' = [for (privateEndpoint, index) in (portalPrivateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-Portal-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'portal'}-${index}' - privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'portal'}-${index}' - properties: { - privateLinkServiceId: account.id - groupIds: [ - privateEndpoint.?service ?? 'portal' +] + +module portal_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.1' = [ + for (privateEndpoint, index) in (portalPrivateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-Portal-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'portal'}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'portal'}-${index}' + properties: { + privateLinkServiceId: account.id + groupIds: [ + privateEndpoint.?service ?? 'portal' + ] + } + } ] - } - } - ] : null - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'portal'}-${index}' - properties: { - privateLinkServiceId: account.id - groupIds: [ - privateEndpoint.?service ?? 'portal' + : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'portal'}-${index}' + properties: { + privateLinkServiceId: account.id + groupIds: [ + privateEndpoint.?service ?? 'portal' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] - -module blob_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.1' = [for (privateEndpoint, index) in (storageBlobPrivateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-Storage-Blob-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'blob'}-${index}' - privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'blob'}-${index}' - properties: { - privateLinkServiceId: account.properties.managedResources.storageAccount - groupIds: [ - privateEndpoint.?service ?? 'blob' +] + +module blob_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.1' = [ + for (privateEndpoint, index) in (storageBlobPrivateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-Storage-Blob-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'blob'}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'blob'}-${index}' + properties: { + privateLinkServiceId: account.properties.managedResources.storageAccount + groupIds: [ + privateEndpoint.?service ?? 'blob' + ] + } + } ] - } - } - ] : null - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'blob'}-${index}' - properties: { - privateLinkServiceId: account.properties.managedResources.storageAccount - groupIds: [ - privateEndpoint.?service ?? 'blob' + : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'blob'}-${index}' + properties: { + privateLinkServiceId: account.properties.managedResources.storageAccount + groupIds: [ + privateEndpoint.?service ?? 'blob' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] - -module queue_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.1' = [for (privateEndpoint, index) in (storageQueuePrivateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-Storage-Queue-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'queue'}-${index}' - privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'queue'}-${index}' - properties: { - privateLinkServiceId: account.properties.managedResources.storageAccount - groupIds: [ - privateEndpoint.?service ?? 'queue' +] + +module queue_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.1' = [ + for (privateEndpoint, index) in (storageQueuePrivateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-Storage-Queue-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'queue'}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'queue'}-${index}' + properties: { + privateLinkServiceId: account.properties.managedResources.storageAccount + groupIds: [ + privateEndpoint.?service ?? 'queue' + ] + } + } ] - } - } - ] : null - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'queue'}-${index}' - properties: { - privateLinkServiceId: account.properties.managedResources.storageAccount - groupIds: [ - privateEndpoint.?service ?? 'queue' + : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'queue'}-${index}' + properties: { + privateLinkServiceId: account.properties.managedResources.storageAccount + groupIds: [ + privateEndpoint.?service ?? 'queue' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] - -module eventHub_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.1' = [for (privateEndpoint, index) in (eventHubPrivateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-Eventhub-Namespace-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'namespace'}-${index}' - privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'namespace'}-${index}' - properties: { - privateLinkServiceId: account.properties.managedResources.eventHubNamespace - groupIds: [ - privateEndpoint.?service ?? 'namespace' +] + +module eventHub_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.1' = [ + for (privateEndpoint, index) in (eventHubPrivateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-Eventhub-Namespace-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'namespace'}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'namespace'}-${index}' + properties: { + privateLinkServiceId: account.properties.managedResources.eventHubNamespace + groupIds: [ + privateEndpoint.?service ?? 'namespace' + ] + } + } ] - } - } - ] : null - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'namespace'}-${index}' - properties: { - privateLinkServiceId: account.properties.managedResources.eventHubNamespace - groupIds: [ - privateEndpoint.?service ?? 'namespace' + : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(account.id, '/'))}-${privateEndpoint.?service ?? 'namespace'}-${index}' + properties: { + privateLinkServiceId: account.properties.managedResources.eventHubNamespace + groupIds: [ + privateEndpoint.?service ?? 'namespace' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] +] -resource account_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(account.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource account_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(account.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: account } - scope: account -}] +] @description('The name of the Purview Account.') output name string = account.name diff --git a/avm/res/purview/account/main.json b/avm/res/purview/account/main.json index 6c09d3b5cc..369cfa5e26 100644 --- a/avm/res/purview/account/main.json +++ b/avm/res/purview/account/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11885849494373802730" + "version": "0.26.54.24096", + "templateHash": "6363425469984006749" }, "name": "Purview Accounts", "description": "This module deploys a Purview Account.", diff --git a/avm/res/purview/account/tests/e2e/defaults/main.test.bicep b/avm/res/purview/account/tests/e2e/defaults/main.test.bicep index 3963519084..d1f45f3886 100644 --- a/avm/res/purview/account/tests/e2e/defaults/main.test.bicep +++ b/avm/res/purview/account/tests/e2e/defaults/main.test.bicep @@ -39,11 +39,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - scope: resourceGroup - params: { - name: '${namePrefix}${serviceShort}001' - location: enforcedLocation +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + scope: resourceGroup + params: { + name: '${namePrefix}${serviceShort}001' + location: enforcedLocation + } } -}] +] diff --git a/avm/res/purview/account/tests/e2e/max/dependencies.bicep b/avm/res/purview/account/tests/e2e/max/dependencies.bicep index 1edeb81930..c04042fcfd 100644 --- a/avm/res/purview/account/tests/e2e/max/dependencies.bicep +++ b/avm/res/purview/account/tests/e2e/max/dependencies.bicep @@ -43,10 +43,12 @@ resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018- } @batchSize(1) -resource privateDNSZones 'Microsoft.Network/privateDnsZones@2020-06-01' = [for privateDNSZone in privateDNSZoneNames: { - name: privateDNSZone - location: 'global' -}] +resource privateDNSZones 'Microsoft.Network/privateDnsZones@2020-06-01' = [ + for privateDNSZone in privateDNSZoneNames: { + name: privateDNSZone + location: 'global' + } +] @description('The resource ID of the created Virtual Network Subnet.') output subnetResourceId string = virtualNetwork.properties.subnets[0].id diff --git a/avm/res/purview/account/tests/e2e/max/main.test.bicep b/avm/res/purview/account/tests/e2e/max/main.test.bicep index 4debba85ac..bd88978cbe 100644 --- a/avm/res/purview/account/tests/e2e/max/main.test.bicep +++ b/avm/res/purview/account/tests/e2e/max/main.test.bicep @@ -64,144 +64,149 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - scope: resourceGroup - params: { - name: '${namePrefix}${serviceShort}001' - location: enforcedLocation - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - managedIdentities: { - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - managedResourceGroupName: '${namePrefix}${serviceShort}001-managed-rg' - publicNetworkAccess: 'Disabled' - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + scope: resourceGroup + params: { + name: '${namePrefix}${serviceShort}001' + location: enforcedLocation + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - { - 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' - } - ] - accountPrivateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.purviewAccountPrivateDNSResourceId + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId ] - service: 'account' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } } - ] - portalPrivateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.purviewPortalPrivateDNSResourceId - ] - service: 'portal' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + managedResourceGroupName: '${namePrefix}${serviceShort}001-managed-rg' + publicNetworkAccess: 'Disabled' + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } - } - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.purviewPortalPrivateDNSResourceId - ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId - } - ] - storageBlobPrivateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.storageBlobPrivateDNSResourceId - ] - service: 'blob' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + ] + roleAssignments: [ + { + roleDefinitionIdOrName: 'Owner' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' } - } - ] - storageQueuePrivateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.storageQueuePrivateDNSResourceId - ] - service: 'queue' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + { + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' } - } - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.storageQueuePrivateDNSResourceId - ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId - } - ] - eventHubPrivateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.eventHubPrivateDNSResourceId - ] - service: 'namespace' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + { + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' } + ] + accountPrivateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.purviewAccountPrivateDNSResourceId + ] + service: 'account' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + ] + portalPrivateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.purviewPortalPrivateDNSResourceId + ] + service: 'portal' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.purviewPortalPrivateDNSResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + } + ] + storageBlobPrivateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.storageBlobPrivateDNSResourceId + ] + service: 'blob' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + ] + storageQueuePrivateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.storageQueuePrivateDNSResourceId + ] + service: 'queue' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.storageQueuePrivateDNSResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + } + ] + eventHubPrivateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.eventHubPrivateDNSResourceId + ] + service: 'namespace' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/purview/account/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/purview/account/tests/e2e/waf-aligned/dependencies.bicep index b6aef8ecb2..fc85bdd382 100644 --- a/avm/res/purview/account/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/purview/account/tests/e2e/waf-aligned/dependencies.bicep @@ -35,10 +35,12 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { } @batchSize(1) -resource privateDNSZones 'Microsoft.Network/privateDnsZones@2020-06-01' = [for privateDNSZone in privateDNSZoneNames: { - name: privateDNSZone - location: 'global' -}] +resource privateDNSZones 'Microsoft.Network/privateDnsZones@2020-06-01' = [ + for privateDNSZone in privateDNSZoneNames: { + name: privateDNSZone + location: 'global' + } +] @description('The resource ID of the created Virtual Network Subnet.') output subnetResourceId string = virtualNetwork.properties.subnets[0].id diff --git a/avm/res/purview/account/tests/e2e/waf-aligned/main.test.bicep b/avm/res/purview/account/tests/e2e/waf-aligned/main.test.bicep index 88ca4c893b..b42f8a72fc 100644 --- a/avm/res/purview/account/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/purview/account/tests/e2e/waf-aligned/main.test.bicep @@ -55,7 +55,6 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}01' eventHubNamespaceName: 'dep-${namePrefix}-evhns-${serviceShort}01' location: enforcedLocation - } } @@ -64,75 +63,77 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - scope: resourceGroup - params: { - name: '${namePrefix}${serviceShort}001' - location: enforcedLocation - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - managedResourceGroupName: '${namePrefix}${serviceShort}001-managed-rg' - publicNetworkAccess: 'Disabled' - diagnosticSettings: [ - { - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - accountPrivateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.purviewAccountPrivateDNSResourceId - ] - service: 'account' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - } - ] - portalPrivateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.purviewPortalPrivateDNSResourceId - ] - service: 'portal' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - } - ] - storageBlobPrivateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.storageBlobPrivateDNSResourceId - ] - service: 'blob' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - } - ] - storageQueuePrivateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.storageQueuePrivateDNSResourceId - ] - service: 'queue' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - } - ] - eventHubPrivateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.eventHubPrivateDNSResourceId - ] - service: 'namespace' - subnetResourceId: nestedDependencies.outputs.subnetResourceId +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + scope: resourceGroup + params: { + name: '${namePrefix}${serviceShort}001' + location: enforcedLocation + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } + managedResourceGroupName: '${namePrefix}${serviceShort}001-managed-rg' + publicNetworkAccess: 'Disabled' + diagnosticSettings: [ + { + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + accountPrivateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.purviewAccountPrivateDNSResourceId + ] + service: 'account' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + } + ] + portalPrivateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.purviewPortalPrivateDNSResourceId + ] + service: 'portal' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + } + ] + storageBlobPrivateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.storageBlobPrivateDNSResourceId + ] + service: 'blob' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + } + ] + storageQueuePrivateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.storageQueuePrivateDNSResourceId + ] + service: 'queue' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + } + ] + eventHubPrivateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.eventHubPrivateDNSResourceId + ] + service: 'namespace' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + } + ] + } + dependsOn: [ + nestedDependencies + diagnosticDependencies ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/recovery-services/vault/backup-config/main.json b/avm/res/recovery-services/vault/backup-config/main.json index e8f0e8c0a5..12babe6214 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.25.53.49325", - "templateHash": "15423985878725052790" + "version": "0.26.54.24096", + "templateHash": "13689565005288174531" }, "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.bicep b/avm/res/recovery-services/vault/backup-fabric/protection-container/main.bicep index 693126a32f..a534228768 100644 --- a/avm/res/recovery-services/vault/backup-fabric/protection-container/main.bicep +++ b/avm/res/recovery-services/vault/backup-fabric/protection-container/main.bicep @@ -58,18 +58,20 @@ resource protectionContainer 'Microsoft.RecoveryServices/vaults/backupFabrics/pr } } -module protectionContainer_protectedItems 'protected-item/main.bicep' = [for (protectedItem, index) in protectedItems: { - name: '${uniqueString(deployment().name, location)}-ProtectedItem-${index}' - params: { - policyId: protectedItem.policyId - name: protectedItem.name - protectedItemType: protectedItem.protectedItemType - protectionContainerName: protectionContainer.name - recoveryVaultName: recoveryVaultName - sourceResourceId: protectedItem.sourceResourceId - location: location +module protectionContainer_protectedItems 'protected-item/main.bicep' = [ + for (protectedItem, index) in protectedItems: { + name: '${uniqueString(deployment().name, location)}-ProtectedItem-${index}' + params: { + policyId: protectedItem.policyId + name: protectedItem.name + protectedItemType: protectedItem.protectedItemType + protectionContainerName: protectionContainer.name + recoveryVaultName: recoveryVaultName + sourceResourceId: protectedItem.sourceResourceId + location: location + } } -}] +] @description('The name of the Resource Group the Protection Container was created in.') output resourceGroupName string = resourceGroup().name 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 9a0b367fcc..56dc62a966 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.25.53.49325", - "templateHash": "5887508216739936022" + "version": "0.26.54.24096", + "templateHash": "16058746935194459972" }, "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.25.53.49325", - "templateHash": "15677187951825533891" + "version": "0.26.54.24096", + "templateHash": "5385249890312845255" }, "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 880a35cef4..76594a6483 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.25.53.49325", - "templateHash": "15677187951825533891" + "version": "0.26.54.24096", + "templateHash": "5385249890312845255" }, "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 53c8a67f66..88ac90efb1 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.25.53.49325", - "templateHash": "3329904805287164035" + "version": "0.26.54.24096", + "templateHash": "53495924931537880" }, "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 829a4157b1..ffabea5a26 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.25.53.49325", - "templateHash": "16823125725342753814" + "version": "0.26.54.24096", + "templateHash": "7323008272687100781" }, "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 16126e1d3d..7b19a5708a 100644 --- a/avm/res/recovery-services/vault/main.bicep +++ b/avm/res/recovery-services/vault/main.bicep @@ -63,44 +63,77 @@ param securitySettings object = {} ]) param publicNetworkAccess string = 'Disabled' -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' : 'None') - userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null -} : null +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' : 'None') + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null + } + : null var builtInRoleNames = { - 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') - 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') - 'Backup Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a795c7a0-d4a2-40c1-ae25-d81f01202912') + 'Backup Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '5e467623-bb1f-42f4-a55d-6e525e11384b' + ) + 'Backup Operator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '00c29273-979b-4161-815c-10b084fb9324' + ) + 'Backup Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'a795c7a0-d4a2-40c1-ae25-d81f01202912' + ) 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'Site Recovery Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567') - 'Site Recovery Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca') - 'Site Recovery Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dbaa88c4-0c30-4179-9fb3-46319faa6149') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' + ) + 'Site Recovery Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '6670b86e-a3f7-4917-ac9b-5d6ab1be4567' + ) + 'Site Recovery Operator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '494ae006-db33-4328-bf46-533a6560a3ca' + ) + 'Site Recovery Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'dbaa88c4-0c30-4179-9fb3-46319faa6149' + ) + 'User Access Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.recoveryservices-vault.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.recoveryservices-vault.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource rsv 'Microsoft.RecoveryServices/vaults@2023-01-01' = { name: name @@ -118,176 +151,232 @@ resource rsv 'Microsoft.RecoveryServices/vaults@2023-01-01' = { } } -module rsv_replicationFabrics 'replication-fabric/main.bicep' = [for (replicationFabric, index) in replicationFabrics: { - name: '${uniqueString(deployment().name, location)}-RSV-Fabric-${index}' - params: { - recoveryVaultName: rsv.name - name: contains(replicationFabric, 'name') ? replicationFabric.name : replicationFabric.location - location: replicationFabric.location - replicationContainers: contains(replicationFabric, 'replicationContainers') ? replicationFabric.replicationContainers : [] +module rsv_replicationFabrics 'replication-fabric/main.bicep' = [ + for (replicationFabric, index) in replicationFabrics: { + name: '${uniqueString(deployment().name, location)}-RSV-Fabric-${index}' + params: { + recoveryVaultName: rsv.name + name: contains(replicationFabric, 'name') ? replicationFabric.name : replicationFabric.location + location: replicationFabric.location + replicationContainers: contains(replicationFabric, 'replicationContainers') + ? replicationFabric.replicationContainers + : [] + } + dependsOn: [ + rsv_replicationPolicies + ] } - dependsOn: [ - rsv_replicationPolicies - ] -}] - -module rsv_replicationPolicies 'replication-policy/main.bicep' = [for (replicationPolicy, index) in replicationPolicies: { - name: '${uniqueString(deployment().name, location)}-RSV-Policy-${index}' - params: { - name: replicationPolicy.name - recoveryVaultName: rsv.name - appConsistentFrequencyInMinutes: contains(replicationPolicy, 'appConsistentFrequencyInMinutes') ? replicationPolicy.appConsistentFrequencyInMinutes : 60 - crashConsistentFrequencyInMinutes: contains(replicationPolicy, 'crashConsistentFrequencyInMinutes') ? replicationPolicy.crashConsistentFrequencyInMinutes : 5 - multiVmSyncStatus: contains(replicationPolicy, 'multiVmSyncStatus') ? replicationPolicy.multiVmSyncStatus : 'Enable' - recoveryPointHistory: contains(replicationPolicy, 'recoveryPointHistory') ? replicationPolicy.recoveryPointHistory : 1440 +] + +module rsv_replicationPolicies 'replication-policy/main.bicep' = [ + for (replicationPolicy, index) in replicationPolicies: { + name: '${uniqueString(deployment().name, location)}-RSV-Policy-${index}' + params: { + name: replicationPolicy.name + recoveryVaultName: rsv.name + appConsistentFrequencyInMinutes: contains(replicationPolicy, 'appConsistentFrequencyInMinutes') + ? replicationPolicy.appConsistentFrequencyInMinutes + : 60 + crashConsistentFrequencyInMinutes: contains(replicationPolicy, 'crashConsistentFrequencyInMinutes') + ? replicationPolicy.crashConsistentFrequencyInMinutes + : 5 + multiVmSyncStatus: contains(replicationPolicy, 'multiVmSyncStatus') + ? replicationPolicy.multiVmSyncStatus + : 'Enable' + recoveryPointHistory: contains(replicationPolicy, 'recoveryPointHistory') + ? replicationPolicy.recoveryPointHistory + : 1440 + } } -}] - -module rsv_backupStorageConfiguration 'backup-storage-config/main.bicep' = if (!empty(backupStorageConfig)) { - name: '${uniqueString(deployment().name, location)}-RSV-BackupStorageConfig' - params: { - recoveryVaultName: rsv.name - storageModelType: backupStorageConfig.storageModelType - crossRegionRestoreFlag: backupStorageConfig.crossRegionRestoreFlag +] + +module rsv_backupStorageConfiguration 'backup-storage-config/main.bicep' = + if (!empty(backupStorageConfig)) { + name: '${uniqueString(deployment().name, location)}-RSV-BackupStorageConfig' + params: { + recoveryVaultName: rsv.name + storageModelType: backupStorageConfig.storageModelType + crossRegionRestoreFlag: backupStorageConfig.crossRegionRestoreFlag + } } -} -module rsv_backupFabric_protectionContainers 'backup-fabric/protection-container/main.bicep' = [for (protectionContainer, index) in protectionContainers: { - name: '${uniqueString(deployment().name, location)}-RSV-ProtectionContainers-${index}' - params: { - recoveryVaultName: rsv.name - name: protectionContainer.name - sourceResourceId: protectionContainer.?sourceResourceId - friendlyName: protectionContainer.?friendlyName - backupManagementType: protectionContainer.?backupManagementType - containerType: protectionContainer.?containerType - protectedItems: contains(protectionContainer, 'protectedItems') ? protectionContainer.protectedItems : [] - location: location +module rsv_backupFabric_protectionContainers 'backup-fabric/protection-container/main.bicep' = [ + for (protectionContainer, index) in protectionContainers: { + name: '${uniqueString(deployment().name, location)}-RSV-ProtectionContainers-${index}' + params: { + recoveryVaultName: rsv.name + name: protectionContainer.name + sourceResourceId: protectionContainer.?sourceResourceId + friendlyName: protectionContainer.?friendlyName + backupManagementType: protectionContainer.?backupManagementType + containerType: protectionContainer.?containerType + protectedItems: contains(protectionContainer, 'protectedItems') ? protectionContainer.protectedItems : [] + location: location + } } -}] - -module rsv_backupPolicies 'backup-policy/main.bicep' = [for (backupPolicy, index) in backupPolicies: { - name: '${uniqueString(deployment().name, location)}-RSV-BackupPolicy-${index}' - params: { - recoveryVaultName: rsv.name - name: backupPolicy.name - properties: backupPolicy.properties +] + +module rsv_backupPolicies 'backup-policy/main.bicep' = [ + for (backupPolicy, index) in backupPolicies: { + name: '${uniqueString(deployment().name, location)}-RSV-BackupPolicy-${index}' + params: { + recoveryVaultName: rsv.name + name: backupPolicy.name + properties: backupPolicy.properties + } } -}] - -module rsv_backupConfig 'backup-config/main.bicep' = if (!empty(backupConfig)) { - name: '${uniqueString(deployment().name, location)}-RSV-BackupConfig' - params: { - recoveryVaultName: rsv.name - name: contains(backupConfig, 'name') ? backupConfig.name : 'vaultconfig' - enhancedSecurityState: contains(backupConfig, 'enhancedSecurityState') ? backupConfig.enhancedSecurityState : 'Enabled' - resourceGuardOperationRequests: contains(backupConfig, 'resourceGuardOperationRequests') ? backupConfig.resourceGuardOperationRequests : [] - softDeleteFeatureState: contains(backupConfig, 'softDeleteFeatureState') ? backupConfig.softDeleteFeatureState : 'Enabled' - storageModelType: contains(backupConfig, 'storageModelType') ? backupConfig.storageModelType : 'GeoRedundant' - storageType: contains(backupConfig, 'storageType') ? backupConfig.storageType : 'GeoRedundant' - storageTypeState: contains(backupConfig, 'storageTypeState') ? backupConfig.storageTypeState : 'Locked' - isSoftDeleteFeatureStateEditable: contains(backupConfig, 'isSoftDeleteFeatureStateEditable') ? backupConfig.isSoftDeleteFeatureStateEditable : true +] + +module rsv_backupConfig 'backup-config/main.bicep' = + if (!empty(backupConfig)) { + name: '${uniqueString(deployment().name, location)}-RSV-BackupConfig' + params: { + recoveryVaultName: rsv.name + name: contains(backupConfig, 'name') ? backupConfig.name : 'vaultconfig' + enhancedSecurityState: contains(backupConfig, 'enhancedSecurityState') + ? backupConfig.enhancedSecurityState + : 'Enabled' + resourceGuardOperationRequests: contains(backupConfig, 'resourceGuardOperationRequests') + ? backupConfig.resourceGuardOperationRequests + : [] + softDeleteFeatureState: contains(backupConfig, 'softDeleteFeatureState') + ? backupConfig.softDeleteFeatureState + : 'Enabled' + storageModelType: contains(backupConfig, 'storageModelType') ? backupConfig.storageModelType : 'GeoRedundant' + storageType: contains(backupConfig, 'storageType') ? backupConfig.storageType : 'GeoRedundant' + storageTypeState: contains(backupConfig, 'storageTypeState') ? backupConfig.storageTypeState : 'Locked' + isSoftDeleteFeatureStateEditable: contains(backupConfig, 'isSoftDeleteFeatureStateEditable') + ? backupConfig.isSoftDeleteFeatureStateEditable + : true + } } -} -module rsv_replicationAlertSettings 'replication-alert-setting/main.bicep' = if (!empty(replicationAlertSettings)) { - name: '${uniqueString(deployment().name, location)}-RSV-replicationAlertSettings' - params: { - name: 'defaultAlertSetting' - recoveryVaultName: rsv.name - customEmailAddresses: contains(replicationAlertSettings, 'customEmailAddresses') ? replicationAlertSettings.customEmailAddresses : [] - locale: contains(replicationAlertSettings, 'locale') ? replicationAlertSettings.locale : '' - sendToOwners: contains(replicationAlertSettings, 'sendToOwners') ? replicationAlertSettings.sendToOwners : 'Send' +module rsv_replicationAlertSettings 'replication-alert-setting/main.bicep' = + if (!empty(replicationAlertSettings)) { + name: '${uniqueString(deployment().name, location)}-RSV-replicationAlertSettings' + params: { + name: 'defaultAlertSetting' + recoveryVaultName: rsv.name + customEmailAddresses: contains(replicationAlertSettings, 'customEmailAddresses') + ? replicationAlertSettings.customEmailAddresses + : [] + locale: contains(replicationAlertSettings, 'locale') ? replicationAlertSettings.locale : '' + sendToOwners: contains(replicationAlertSettings, 'sendToOwners') ? replicationAlertSettings.sendToOwners : 'Send' + } } -} -resource rsv_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.' +resource rsv_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: rsv } - scope: rsv -} -resource rsv_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource rsv_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: rsv } - scope: rsv -}] - -module rsv_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-RSV-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(rsv.id, '/'))}-${privateEndpoint.?service ?? 'AzureSiteRecovery'}-${index}' - privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(rsv.id, '/'))}-${privateEndpoint.?service ?? 'AzureSiteRecovery'}-${index}' - properties: { - privateLinkServiceId: rsv.id - groupIds: [ - privateEndpoint.?service ?? 'AzureSiteRecovery' +] + +module rsv_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-RSV-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(rsv.id, '/'))}-${privateEndpoint.?service ?? 'AzureSiteRecovery'}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(rsv.id, '/'))}-${privateEndpoint.?service ?? 'AzureSiteRecovery'}-${index}' + properties: { + privateLinkServiceId: rsv.id + groupIds: [ + privateEndpoint.?service ?? 'AzureSiteRecovery' + ] + } + } ] - } - } - ] : null - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(rsv.id, '/'))}-${privateEndpoint.?service ?? 'AzureSiteRecovery'}-${index}' - properties: { - privateLinkServiceId: rsv.id - groupIds: [ - privateEndpoint.?service ?? 'AzureSiteRecovery' + : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(rsv.id, '/'))}-${privateEndpoint.?service ?? 'AzureSiteRecovery'}-${index}' + properties: { + privateLinkServiceId: rsv.id + groupIds: [ + privateEndpoint.?service ?? 'AzureSiteRecovery' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] +] -resource rsv_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(rsv.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource rsv_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(rsv.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: rsv } - scope: rsv -}] +] @description('The resource ID of the recovery services vault.') output resourceId string = rsv.id diff --git a/avm/res/recovery-services/vault/main.json b/avm/res/recovery-services/vault/main.json index 686a7aa5d3..83b7e86188 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.25.53.49325", - "templateHash": "916737030536129910" + "version": "0.26.54.24096", + "templateHash": "544770798724307182" }, "name": "Recovery Services Vaults", "description": "This module deploys a Recovery Services Vault.", @@ -725,8 +725,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "9213187265421923503" + "version": "0.26.54.24096", + "templateHash": "10579941098853248837" }, "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.", @@ -804,8 +804,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "584392949528635994" + "version": "0.26.54.24096", + "templateHash": "16016202718205451628" }, "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.", @@ -887,8 +887,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "8286726590589779511" + "version": "0.26.54.24096", + "templateHash": "16134780575393361186" }, "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.", @@ -1096,8 +1096,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "12506498029720805552" + "version": "0.26.54.24096", + "templateHash": "13701757307300485900" }, "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.", @@ -1221,8 +1221,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16823125725342753814" + "version": "0.26.54.24096", + "templateHash": "7323008272687100781" }, "name": "Recovery Services Vault Backup Storage Config", "description": "This module deploys a Recovery Service Vault Backup Storage Configuration.", @@ -1347,8 +1347,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "5887508216739936022" + "version": "0.26.54.24096", + "templateHash": "16058746935194459972" }, "name": "Recovery Services Vault Protection Container", "description": "This module deploys a Recovery Services Vault Protection Container.", @@ -1486,8 +1486,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "15677187951825533891" + "version": "0.26.54.24096", + "templateHash": "5385249890312845255" }, "name": "Recovery Service Vaults Protection Container Protected Item", "description": "This module deploys a Recovery Services Vault Protection Container Protected Item.", @@ -1652,8 +1652,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3329904805287164035" + "version": "0.26.54.24096", + "templateHash": "53495924931537880" }, "name": "Recovery Services Vault Backup Policies", "description": "This module deploys a Recovery Services Vault Backup Policy.", @@ -1745,8 +1745,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "15423985878725052790" + "version": "0.26.54.24096", + "templateHash": "13689565005288174531" }, "name": "Recovery Services Vault Backup Config", "description": "This module deploys a Recovery Services Vault Backup Config.", @@ -1912,8 +1912,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "15609344101830369541" + "version": "0.26.54.24096", + "templateHash": "7725737508882142877" }, "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 a3659c2417..2ce087db13 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.25.53.49325", - "templateHash": "15609344101830369541" + "version": "0.26.54.24096", + "templateHash": "7725737508882142877" }, "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/main.bicep b/avm/res/recovery-services/vault/replication-fabric/main.bicep index 5156981ed4..e7b7f91869 100644 --- a/avm/res/recovery-services/vault/replication-fabric/main.bicep +++ b/avm/res/recovery-services/vault/replication-fabric/main.bicep @@ -26,18 +26,22 @@ resource replicationFabric 'Microsoft.RecoveryServices/vaults/replicationFabrics } } -module fabric_replicationContainers 'replication-protection-container/main.bicep' = [for (container, index) in replicationContainers: { - name: '${deployment().name}-RCont-${index}' - params: { - name: container.name - recoveryVaultName: recoveryVaultName - replicationFabricName: name - replicationContainerMappings: contains(container, 'replicationContainerMappings') ? container.replicationContainerMappings : [] +module fabric_replicationContainers 'replication-protection-container/main.bicep' = [ + for (container, index) in replicationContainers: { + name: '${deployment().name}-RCont-${index}' + params: { + name: container.name + recoveryVaultName: recoveryVaultName + replicationFabricName: name + replicationContainerMappings: contains(container, 'replicationContainerMappings') + ? container.replicationContainerMappings + : [] + } + dependsOn: [ + replicationFabric + ] } - dependsOn: [ - replicationFabric - ] -}] +] @description('The name of the replication fabric.') output name string = replicationFabric.name diff --git a/avm/res/recovery-services/vault/replication-fabric/main.json b/avm/res/recovery-services/vault/replication-fabric/main.json index 5be50536e8..3b86dad90a 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.25.53.49325", - "templateHash": "9213187265421923503" + "version": "0.26.54.24096", + "templateHash": "10579941098853248837" }, "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.", @@ -83,8 +83,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "584392949528635994" + "version": "0.26.54.24096", + "templateHash": "16016202718205451628" }, "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.", @@ -166,8 +166,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "8286726590589779511" + "version": "0.26.54.24096", + "templateHash": "16134780575393361186" }, "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 4e23d2b5d3..95114d9bcb 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 @@ -27,23 +27,29 @@ resource replicationContainer 'Microsoft.RecoveryServices/vaults/replicationFabr } } -module fabric_container_containerMappings 'replication-protection-container-mapping/main.bicep' = [for (mapping, index) in replicationContainerMappings: { - name: '${deployment().name}-Map-${index}' - params: { - name: contains(mapping, 'name') ? mapping.name : '' - policyId: contains(mapping, 'policyId') ? mapping.policyId : '' - policyName: contains(mapping, 'policyName') ? mapping.policyName : '' - recoveryVaultName: recoveryVaultName - replicationFabricName: replicationFabricName - sourceProtectionContainerName: name - targetProtectionContainerId: contains(mapping, 'targetProtectionContainerId') ? mapping.targetProtectionContainerId : '' - targetContainerFabricName: contains(mapping, 'targetContainerFabricName') ? mapping.targetContainerFabricName : replicationFabricName - targetContainerName: contains(mapping, 'targetContainerName') ? mapping.targetContainerName : '' +module fabric_container_containerMappings 'replication-protection-container-mapping/main.bicep' = [ + for (mapping, index) in replicationContainerMappings: { + name: '${deployment().name}-Map-${index}' + params: { + name: contains(mapping, 'name') ? mapping.name : '' + policyId: contains(mapping, 'policyId') ? mapping.policyId : '' + policyName: contains(mapping, 'policyName') ? mapping.policyName : '' + recoveryVaultName: recoveryVaultName + replicationFabricName: replicationFabricName + sourceProtectionContainerName: name + targetProtectionContainerId: contains(mapping, 'targetProtectionContainerId') + ? mapping.targetProtectionContainerId + : '' + targetContainerFabricName: contains(mapping, 'targetContainerFabricName') + ? mapping.targetContainerFabricName + : replicationFabricName + targetContainerName: contains(mapping, 'targetContainerName') ? mapping.targetContainerName : '' + } + dependsOn: [ + replicationContainer + ] } - dependsOn: [ - replicationContainer - ] -}] +] @description('The name of the replication container.') output name string = replicationContainer.name 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 78784a2039..61cab34cde 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.25.53.49325", - "templateHash": "584392949528635994" + "version": "0.26.54.24096", + "templateHash": "16016202718205451628" }, "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.", @@ -87,8 +87,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "8286726590589779511" + "version": "0.26.54.24096", + "templateHash": "16134780575393361186" }, "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.bicep b/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/replication-protection-container-mapping/main.bicep index 1e0fc30ec9..2d50d4933d 100644 --- a/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/replication-protection-container-mapping/main.bicep +++ b/avm/res/recovery-services/vault/replication-fabric/replication-protection-container/replication-protection-container-mapping/main.bicep @@ -31,9 +31,20 @@ param policyName string = '' @description('Optional. The name of the replication container mapping. If not provided, it will be automatically generated as `-`.') param name string = '' -var policyResourceId = policyId != '' ? policyId : subscriptionResourceId('Microsoft.RecoveryServices/vaults/replicationPolicies', recoveryVaultName, policyName) -var targetProtectionContainerResourceId = targetProtectionContainerId != '' ? targetProtectionContainerId : subscriptionResourceId('Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers', recoveryVaultName, targetContainerFabricName, targetContainerName) -var mappingName = !empty(name) ? name : '${sourceProtectionContainerName}-${split(targetProtectionContainerResourceId, '/')[10]}' +var policyResourceId = policyId != '' + ? policyId + : subscriptionResourceId('Microsoft.RecoveryServices/vaults/replicationPolicies', recoveryVaultName, policyName) +var targetProtectionContainerResourceId = targetProtectionContainerId != '' + ? targetProtectionContainerId + : subscriptionResourceId( + 'Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers', + recoveryVaultName, + targetContainerFabricName, + targetContainerName + ) +var mappingName = !empty(name) + ? name + : '${sourceProtectionContainerName}-${split(targetProtectionContainerResourceId, '/')[10]}' resource replicationContainer 'Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings@2022-10-01' = { name: '${recoveryVaultName}/${replicationFabricName}/${sourceProtectionContainerName}/${mappingName}' 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 2c633c2461..2285b6b368 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.25.53.49325", - "templateHash": "8286726590589779511" + "version": "0.26.54.24096", + "templateHash": "16134780575393361186" }, "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 e67e01104b..488af5ff5a 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.25.53.49325", - "templateHash": "12506498029720805552" + "version": "0.26.54.24096", + "templateHash": "13701757307300485900" }, "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/recovery-services/vault/tests/e2e/defaults/main.test.bicep b/avm/res/recovery-services/vault/tests/e2e/defaults/main.test.bicep index 3444eae1ee..7431e75ceb 100644 --- a/avm/res/recovery-services/vault/tests/e2e/defaults/main.test.bicep +++ b/avm/res/recovery-services/vault/tests/e2e/defaults/main.test.bicep @@ -39,24 +39,26 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - location: resourceLocation - enableTelemetry: enableDefaultTelemetry - name: '${namePrefix}${serviceShort}001' - replicationAlertSettings: { - customEmailAddresses: [ - 'test.user@testcompany.com' - ] - locale: 'en-US' - sendToOwners: 'Send' - } - securitySettings: { - immutabilitySettings: { - state: 'Unlocked' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + enableTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + replicationAlertSettings: { + customEmailAddresses: [ + 'test.user@testcompany.com' + ] + locale: 'en-US' + sendToOwners: 'Send' + } + securitySettings: { + immutabilitySettings: { + state: 'Unlocked' + } } } } -}] +] diff --git a/avm/res/recovery-services/vault/tests/e2e/dr/main.test.bicep b/avm/res/recovery-services/vault/tests/e2e/dr/main.test.bicep index f372f3c6e7..adc3b5f0c2 100644 --- a/avm/res/recovery-services/vault/tests/e2e/dr/main.test.bicep +++ b/avm/res/recovery-services/vault/tests/e2e/dr/main.test.bicep @@ -39,72 +39,74 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // var rsvName = '${namePrefix}${serviceShort}001' @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - location: resourceLocation - enableTelemetry: enableDefaultTelemetry - name: rsvName - replicationFabrics: [ - { - location: 'NorthEurope' - replicationContainers: [ - { - name: 'ne-container1' - replicationContainerMappings: [ - { - policyName: 'Default_values' - targetContainerName: 'pluto' - targetProtectionContainerId: '${resourceGroup.id}/providers/Microsoft.RecoveryServices/vaults/${rsvName}/replicationFabrics/NorthEurope/replicationProtectionContainers/ne-container2' - } - ] - } - { - name: 'ne-container2' - replicationContainerMappings: [ - { - policyName: 'Default_values' - targetContainerFabricName: 'WE-2' - targetContainerName: 'we-container1' - } - ] - } - ] +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + enableTelemetry: enableDefaultTelemetry + name: rsvName + replicationFabrics: [ + { + location: 'NorthEurope' + replicationContainers: [ + { + name: 'ne-container1' + replicationContainerMappings: [ + { + policyName: 'Default_values' + targetContainerName: 'pluto' + targetProtectionContainerId: '${resourceGroup.id}/providers/Microsoft.RecoveryServices/vaults/${rsvName}/replicationFabrics/NorthEurope/replicationProtectionContainers/ne-container2' + } + ] + } + { + name: 'ne-container2' + replicationContainerMappings: [ + { + policyName: 'Default_values' + targetContainerFabricName: 'WE-2' + targetContainerName: 'we-container1' + } + ] + } + ] + } + { + location: 'WestEurope' + name: 'WE-2' + replicationContainers: [ + { + name: 'we-container1' + replicationContainerMappings: [ + { + policyName: 'Default_values' + targetContainerFabricName: 'NorthEurope' + targetContainerName: 'ne-container2' + } + ] + } + ] + } + ] + replicationPolicies: [ + { + name: 'Default_values' + } + { + appConsistentFrequencyInMinutes: 240 + crashConsistentFrequencyInMinutes: 7 + multiVmSyncStatus: 'Disable' + name: 'Custom_values' + recoveryPointHistory: 2880 + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - { - location: 'WestEurope' - name: 'WE-2' - replicationContainers: [ - { - name: 'we-container1' - replicationContainerMappings: [ - { - policyName: 'Default_values' - targetContainerFabricName: 'NorthEurope' - targetContainerName: 'ne-container2' - } - ] - } - ] - } - ] - replicationPolicies: [ - { - name: 'Default_values' - } - { - appConsistentFrequencyInMinutes: 240 - crashConsistentFrequencyInMinutes: 7 - multiVmSyncStatus: 'Disable' - name: 'Custom_values' - recoveryPointHistory: 2880 - } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/recovery-services/vault/tests/e2e/max/main.test.bicep b/avm/res/recovery-services/vault/tests/e2e/max/main.test.bicep index 1232ad832e..3c5618b5b6 100644 --- a/avm/res/recovery-services/vault/tests/e2e/max/main.test.bicep +++ b/avm/res/recovery-services/vault/tests/e2e/max/main.test.bicep @@ -63,371 +63,376 @@ 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: { - location: resourceLocation - enableTelemetry: enableDefaultTelemetry - name: '${namePrefix}${serviceShort}001' - backupConfig: { - enhancedSecurityState: 'Disabled' - softDeleteFeatureState: 'Disabled' - } - backupPolicies: [ - { - name: 'VMpolicy' - properties: { - backupManagementType: 'AzureIaasVM' - instantRPDetails: {} - instantRpRetentionRangeInDays: 2 - protectedItemsCount: 0 - retentionPolicy: { - dailySchedule: { - retentionDuration: { - count: 180 - durationType: 'Days' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + enableTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + backupConfig: { + enhancedSecurityState: 'Disabled' + softDeleteFeatureState: 'Disabled' + } + backupPolicies: [ + { + name: 'VMpolicy' + properties: { + backupManagementType: 'AzureIaasVM' + instantRPDetails: {} + instantRpRetentionRangeInDays: 2 + protectedItemsCount: 0 + retentionPolicy: { + dailySchedule: { + retentionDuration: { + count: 180 + durationType: 'Days' + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] } - retentionTimes: [ - '2019-11-07T07:00:00Z' - ] - } - monthlySchedule: { - retentionDuration: { - count: 60 - durationType: 'Months' + monthlySchedule: { + retentionDuration: { + count: 60 + durationType: 'Months' + } + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] } - retentionScheduleFormatType: 'Weekly' - retentionScheduleWeekly: { + retentionPolicyType: 'LongTermRetentionPolicy' + weeklySchedule: { daysOfTheWeek: [ 'Sunday' ] - weeksOfTheMonth: [ - 'First' + retentionDuration: { + count: 12 + durationType: 'Weeks' + } + retentionTimes: [ + '2019-11-07T07:00:00Z' ] } - retentionTimes: [ - '2019-11-07T07:00:00Z' - ] - } - retentionPolicyType: 'LongTermRetentionPolicy' - weeklySchedule: { - daysOfTheWeek: [ - 'Sunday' - ] - retentionDuration: { - count: 12 - durationType: 'Weeks' - } - retentionTimes: [ - '2019-11-07T07:00:00Z' - ] - } - yearlySchedule: { - monthsOfYear: [ - 'January' - ] - retentionDuration: { - count: 10 - durationType: 'Years' - } - retentionScheduleFormatType: 'Weekly' - retentionScheduleWeekly: { - daysOfTheWeek: [ - 'Sunday' + yearlySchedule: { + monthsOfYear: [ + 'January' ] - weeksOfTheMonth: [ - 'First' + retentionDuration: { + count: 10 + durationType: 'Years' + } + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T07:00:00Z' ] } - retentionTimes: [ + } + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunFrequency: 'Daily' + scheduleRunTimes: [ '2019-11-07T07:00:00Z' ] + scheduleWeeklyFrequency: 0 } - } - schedulePolicy: { - schedulePolicyType: 'SimpleSchedulePolicy' - scheduleRunFrequency: 'Daily' - scheduleRunTimes: [ - '2019-11-07T07:00:00Z' - ] - scheduleWeeklyFrequency: 0 - } - timeZone: 'UTC' - } - } - { - name: 'sqlpolicy' - properties: { - backupManagementType: 'AzureWorkload' - protectedItemsCount: 0 - settings: { - isCompression: true - issqlcompression: true timeZone: 'UTC' } - subProtectionPolicy: [ - { - policyType: 'Full' - retentionPolicy: { - monthlySchedule: { - retentionDuration: { - count: 60 - durationType: 'Months' + } + { + name: 'sqlpolicy' + properties: { + backupManagementType: 'AzureWorkload' + protectedItemsCount: 0 + settings: { + isCompression: true + issqlcompression: true + timeZone: 'UTC' + } + subProtectionPolicy: [ + { + policyType: 'Full' + retentionPolicy: { + monthlySchedule: { + retentionDuration: { + count: 60 + durationType: 'Months' + } + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T22:00:00Z' + ] } - retentionScheduleFormatType: 'Weekly' - retentionScheduleWeekly: { + retentionPolicyType: 'LongTermRetentionPolicy' + weeklySchedule: { daysOfTheWeek: [ 'Sunday' ] - weeksOfTheMonth: [ - 'First' + retentionDuration: { + count: 104 + durationType: 'Weeks' + } + retentionTimes: [ + '2019-11-07T22:00:00Z' + ] + } + yearlySchedule: { + monthsOfYear: [ + 'January' + ] + retentionDuration: { + count: 10 + durationType: 'Years' + } + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T22:00:00Z' ] } - retentionTimes: [ - '2019-11-07T22:00:00Z' - ] } - retentionPolicyType: 'LongTermRetentionPolicy' - weeklySchedule: { - daysOfTheWeek: [ + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunDays: [ 'Sunday' ] - retentionDuration: { - count: 104 - durationType: 'Weeks' - } - retentionTimes: [ + scheduleRunFrequency: 'Weekly' + scheduleRunTimes: [ '2019-11-07T22:00:00Z' ] + scheduleWeeklyFrequency: 0 } - yearlySchedule: { - monthsOfYear: [ - 'January' - ] + } + { + policyType: 'Differential' + retentionPolicy: { retentionDuration: { - count: 10 - durationType: 'Years' - } - retentionScheduleFormatType: 'Weekly' - retentionScheduleWeekly: { - daysOfTheWeek: [ - 'Sunday' - ] - weeksOfTheMonth: [ - 'First' - ] + count: 30 + durationType: 'Days' } - retentionTimes: [ - '2019-11-07T22:00:00Z' + retentionPolicyType: 'SimpleRetentionPolicy' + } + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunDays: [ + 'Monday' + ] + scheduleRunFrequency: 'Weekly' + scheduleRunTimes: [ + '2017-03-07T02:00:00Z' ] + scheduleWeeklyFrequency: 0 } } - schedulePolicy: { - schedulePolicyType: 'SimpleSchedulePolicy' - scheduleRunDays: [ - 'Sunday' - ] - scheduleRunFrequency: 'Weekly' - scheduleRunTimes: [ - '2019-11-07T22:00:00Z' - ] - scheduleWeeklyFrequency: 0 + { + policyType: 'Log' + retentionPolicy: { + retentionDuration: { + count: 15 + durationType: 'Days' + } + retentionPolicyType: 'SimpleRetentionPolicy' + } + schedulePolicy: { + scheduleFrequencyInMins: 120 + schedulePolicyType: 'LogSchedulePolicy' + } } - } - { - policyType: 'Differential' - retentionPolicy: { + ] + workLoadType: 'SQLDataBase' + } + } + { + name: 'filesharepolicy' + properties: { + backupManagementType: 'AzureStorage' + protectedItemsCount: 0 + retentionPolicy: { + dailySchedule: { retentionDuration: { count: 30 durationType: 'Days' } - retentionPolicyType: 'SimpleRetentionPolicy' - } - schedulePolicy: { - schedulePolicyType: 'SimpleSchedulePolicy' - scheduleRunDays: [ - 'Monday' - ] - scheduleRunFrequency: 'Weekly' - scheduleRunTimes: [ - '2017-03-07T02:00:00Z' + retentionTimes: [ + '2019-11-07T04:30:00Z' ] - scheduleWeeklyFrequency: 0 - } - } - { - policyType: 'Log' - retentionPolicy: { - retentionDuration: { - count: 15 - durationType: 'Days' - } - retentionPolicyType: 'SimpleRetentionPolicy' - } - schedulePolicy: { - scheduleFrequencyInMins: 120 - schedulePolicyType: 'LogSchedulePolicy' } + retentionPolicyType: 'LongTermRetentionPolicy' } - ] - workLoadType: 'SQLDataBase' - } - } - { - name: 'filesharepolicy' - properties: { - backupManagementType: 'AzureStorage' - protectedItemsCount: 0 - retentionPolicy: { - dailySchedule: { - retentionDuration: { - count: 30 - durationType: 'Days' - } - retentionTimes: [ + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunFrequency: 'Daily' + scheduleRunTimes: [ '2019-11-07T04:30:00Z' ] + scheduleWeeklyFrequency: 0 } - retentionPolicyType: 'LongTermRetentionPolicy' - } - schedulePolicy: { - schedulePolicyType: 'SimpleSchedulePolicy' - scheduleRunFrequency: 'Daily' - scheduleRunTimes: [ - '2019-11-07T04:30:00Z' - ] - scheduleWeeklyFrequency: 0 + timeZone: 'UTC' + workloadType: 'AzureFileShare' } - timeZone: 'UTC' - workloadType: 'AzureFileShare' } - } - ] - backupStorageConfig: { - crossRegionRestoreFlag: true - storageModelType: 'GeoRedundant' - } - replicationAlertSettings: { - customEmailAddresses: [ - 'test.user@testcompany.com' ] - locale: 'en-US' - sendToOwners: 'Send' - } - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } + backupStorageConfig: { + crossRegionRestoreFlag: true + storageModelType: 'GeoRedundant' + } + replicationAlertSettings: { + customEmailAddresses: [ + 'test.user@testcompany.com' ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + locale: 'en-US' + sendToOwners: 'Send' } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - managedIdentities: { - systemAssigned: true - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } ] - } - privateEndpoints: [ - { - ipConfigurations: [ - { - name: 'myIpConfig-1' - properties: { - groupId: 'AzureSiteRecovery' - memberName: 'SiteRecovery-tel1' - privateIPAddress: '10.0.0.10' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + privateEndpoints: [ + { + ipConfigurations: [ + { + name: 'myIpConfig-1' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-tel1' + privateIPAddress: '10.0.0.10' + } } - } - { - name: 'myIPconfig-2' - properties: { - groupId: 'AzureSiteRecovery' - memberName: 'SiteRecovery-prot2' - privateIPAddress: '10.0.0.11' + { + name: 'myIPconfig-2' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-prot2' + privateIPAddress: '10.0.0.11' + } } - } - { - name: 'myIPconfig-3' - properties: { - groupId: 'AzureSiteRecovery' - memberName: 'SiteRecovery-srs1' - privateIPAddress: '10.0.0.12' + { + name: 'myIPconfig-3' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-srs1' + privateIPAddress: '10.0.0.12' + } } - } - { - name: 'myIPconfig-4' - properties: { - groupId: 'AzureSiteRecovery' - memberName: 'SiteRecovery-rcm1' - privateIPAddress: '10.0.0.13' + { + name: 'myIPconfig-4' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-rcm1' + privateIPAddress: '10.0.0.13' + } } - } - { - name: 'myIPconfig-5' - properties: { - groupId: 'AzureSiteRecovery' - memberName: 'SiteRecovery-id1' - privateIPAddress: '10.0.0.14' + { + name: 'myIPconfig-5' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-id1' + privateIPAddress: '10.0.0.14' + } } + ] + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + } + ] + 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' + } + ] + monitoringSettings: { + azureMonitorAlertSettings: { + alertsForAllJobFailures: 'Enabled' + } + classicAlertSettings: { + alertsForCriticalOperations: 'Enabled' } } - ] - 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' - } - ] - monitoringSettings: { - azureMonitorAlertSettings: { - alertsForAllJobFailures: 'Enabled' - } - classicAlertSettings: { - alertsForCriticalOperations: 'Enabled' + securitySettings: { + immutabilitySettings: { + state: 'Unlocked' + } } - } - securitySettings: { - immutabilitySettings: { - state: 'Unlocked' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } } -}] +] diff --git a/avm/res/recovery-services/vault/tests/e2e/waf-aligned/main.test.bicep b/avm/res/recovery-services/vault/tests/e2e/waf-aligned/main.test.bicep index 22605d1d30..6b74206104 100644 --- a/avm/res/recovery-services/vault/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/recovery-services/vault/tests/e2e/waf-aligned/main.test.bicep @@ -63,354 +63,356 @@ 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: { - location: resourceLocation - enableTelemetry: enableDefaultTelemetry - name: '${namePrefix}${serviceShort}001' - backupConfig: { - enhancedSecurityState: 'Disabled' - softDeleteFeatureState: 'Disabled' - } - backupPolicies: [ - { - name: 'VMpolicy' - properties: { - backupManagementType: 'AzureIaasVM' - instantRPDetails: {} - instantRpRetentionRangeInDays: 2 - protectedItemsCount: 0 - retentionPolicy: { - dailySchedule: { - retentionDuration: { - count: 180 - durationType: 'Days' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + enableTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + backupConfig: { + enhancedSecurityState: 'Disabled' + softDeleteFeatureState: 'Disabled' + } + backupPolicies: [ + { + name: 'VMpolicy' + properties: { + backupManagementType: 'AzureIaasVM' + instantRPDetails: {} + instantRpRetentionRangeInDays: 2 + protectedItemsCount: 0 + retentionPolicy: { + dailySchedule: { + retentionDuration: { + count: 180 + durationType: 'Days' + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] } - retentionTimes: [ - '2019-11-07T07:00:00Z' - ] - } - monthlySchedule: { - retentionDuration: { - count: 60 - durationType: 'Months' + monthlySchedule: { + retentionDuration: { + count: 60 + durationType: 'Months' + } + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] } - retentionScheduleFormatType: 'Weekly' - retentionScheduleWeekly: { + retentionPolicyType: 'LongTermRetentionPolicy' + weeklySchedule: { daysOfTheWeek: [ 'Sunday' ] - weeksOfTheMonth: [ - 'First' + retentionDuration: { + count: 12 + durationType: 'Weeks' + } + retentionTimes: [ + '2019-11-07T07:00:00Z' ] } - retentionTimes: [ - '2019-11-07T07:00:00Z' - ] - } - retentionPolicyType: 'LongTermRetentionPolicy' - weeklySchedule: { - daysOfTheWeek: [ - 'Sunday' - ] - retentionDuration: { - count: 12 - durationType: 'Weeks' - } - retentionTimes: [ - '2019-11-07T07:00:00Z' - ] - } - yearlySchedule: { - monthsOfYear: [ - 'January' - ] - retentionDuration: { - count: 10 - durationType: 'Years' - } - retentionScheduleFormatType: 'Weekly' - retentionScheduleWeekly: { - daysOfTheWeek: [ - 'Sunday' + yearlySchedule: { + monthsOfYear: [ + 'January' ] - weeksOfTheMonth: [ - 'First' + retentionDuration: { + count: 10 + durationType: 'Years' + } + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T07:00:00Z' ] } - retentionTimes: [ + } + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunFrequency: 'Daily' + scheduleRunTimes: [ '2019-11-07T07:00:00Z' ] + scheduleWeeklyFrequency: 0 } - } - schedulePolicy: { - schedulePolicyType: 'SimpleSchedulePolicy' - scheduleRunFrequency: 'Daily' - scheduleRunTimes: [ - '2019-11-07T07:00:00Z' - ] - scheduleWeeklyFrequency: 0 - } - timeZone: 'UTC' - } - } - { - name: 'sqlpolicy' - properties: { - backupManagementType: 'AzureWorkload' - protectedItemsCount: 0 - settings: { - isCompression: true - issqlcompression: true timeZone: 'UTC' } - subProtectionPolicy: [ - { - policyType: 'Full' - retentionPolicy: { - monthlySchedule: { - retentionDuration: { - count: 60 - durationType: 'Months' + } + { + name: 'sqlpolicy' + properties: { + backupManagementType: 'AzureWorkload' + protectedItemsCount: 0 + settings: { + isCompression: true + issqlcompression: true + timeZone: 'UTC' + } + subProtectionPolicy: [ + { + policyType: 'Full' + retentionPolicy: { + monthlySchedule: { + retentionDuration: { + count: 60 + durationType: 'Months' + } + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T22:00:00Z' + ] } - retentionScheduleFormatType: 'Weekly' - retentionScheduleWeekly: { + retentionPolicyType: 'LongTermRetentionPolicy' + weeklySchedule: { daysOfTheWeek: [ 'Sunday' ] - weeksOfTheMonth: [ - 'First' + retentionDuration: { + count: 104 + durationType: 'Weeks' + } + retentionTimes: [ + '2019-11-07T22:00:00Z' + ] + } + yearlySchedule: { + monthsOfYear: [ + 'January' + ] + retentionDuration: { + count: 10 + durationType: 'Years' + } + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T22:00:00Z' ] } - retentionTimes: [ - '2019-11-07T22:00:00Z' - ] } - retentionPolicyType: 'LongTermRetentionPolicy' - weeklySchedule: { - daysOfTheWeek: [ + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunDays: [ 'Sunday' ] - retentionDuration: { - count: 104 - durationType: 'Weeks' - } - retentionTimes: [ + scheduleRunFrequency: 'Weekly' + scheduleRunTimes: [ '2019-11-07T22:00:00Z' ] + scheduleWeeklyFrequency: 0 } - yearlySchedule: { - monthsOfYear: [ - 'January' - ] + } + { + policyType: 'Differential' + retentionPolicy: { retentionDuration: { - count: 10 - durationType: 'Years' - } - retentionScheduleFormatType: 'Weekly' - retentionScheduleWeekly: { - daysOfTheWeek: [ - 'Sunday' - ] - weeksOfTheMonth: [ - 'First' - ] + count: 30 + durationType: 'Days' } - retentionTimes: [ - '2019-11-07T22:00:00Z' + retentionPolicyType: 'SimpleRetentionPolicy' + } + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunDays: [ + 'Monday' ] + scheduleRunFrequency: 'Weekly' + scheduleRunTimes: [ + '2017-03-07T02:00:00Z' + ] + scheduleWeeklyFrequency: 0 } } - schedulePolicy: { - schedulePolicyType: 'SimpleSchedulePolicy' - scheduleRunDays: [ - 'Sunday' - ] - scheduleRunFrequency: 'Weekly' - scheduleRunTimes: [ - '2019-11-07T22:00:00Z' - ] - scheduleWeeklyFrequency: 0 + { + policyType: 'Log' + retentionPolicy: { + retentionDuration: { + count: 15 + durationType: 'Days' + } + retentionPolicyType: 'SimpleRetentionPolicy' + } + schedulePolicy: { + scheduleFrequencyInMins: 120 + schedulePolicyType: 'LogSchedulePolicy' + } } - } - { - policyType: 'Differential' - retentionPolicy: { + ] + workLoadType: 'SQLDataBase' + } + } + { + name: 'filesharepolicy' + properties: { + backupManagementType: 'AzureStorage' + protectedItemsCount: 0 + retentionPolicy: { + dailySchedule: { retentionDuration: { count: 30 durationType: 'Days' } - retentionPolicyType: 'SimpleRetentionPolicy' - } - schedulePolicy: { - schedulePolicyType: 'SimpleSchedulePolicy' - scheduleRunDays: [ - 'Monday' - ] - scheduleRunFrequency: 'Weekly' - scheduleRunTimes: [ - '2017-03-07T02:00:00Z' + retentionTimes: [ + '2019-11-07T04:30:00Z' ] - scheduleWeeklyFrequency: 0 - } - } - { - policyType: 'Log' - retentionPolicy: { - retentionDuration: { - count: 15 - durationType: 'Days' - } - retentionPolicyType: 'SimpleRetentionPolicy' - } - schedulePolicy: { - scheduleFrequencyInMins: 120 - schedulePolicyType: 'LogSchedulePolicy' } + retentionPolicyType: 'LongTermRetentionPolicy' } - ] - workLoadType: 'SQLDataBase' - } - } - { - name: 'filesharepolicy' - properties: { - backupManagementType: 'AzureStorage' - protectedItemsCount: 0 - retentionPolicy: { - dailySchedule: { - retentionDuration: { - count: 30 - durationType: 'Days' - } - retentionTimes: [ + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunFrequency: 'Daily' + scheduleRunTimes: [ '2019-11-07T04:30:00Z' ] + scheduleWeeklyFrequency: 0 } - retentionPolicyType: 'LongTermRetentionPolicy' - } - schedulePolicy: { - schedulePolicyType: 'SimpleSchedulePolicy' - scheduleRunFrequency: 'Daily' - scheduleRunTimes: [ - '2019-11-07T04:30:00Z' - ] - scheduleWeeklyFrequency: 0 + timeZone: 'UTC' + workloadType: 'AzureFileShare' } - timeZone: 'UTC' - workloadType: 'AzureFileShare' } - } - ] - backupStorageConfig: { - crossRegionRestoreFlag: true - storageModelType: 'GeoRedundant' - } - replicationAlertSettings: { - customEmailAddresses: [ - 'test.user@testcompany.com' ] - locale: 'en-US' - sendToOwners: 'Send' - } - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } + backupStorageConfig: { + crossRegionRestoreFlag: true + storageModelType: 'GeoRedundant' + } + replicationAlertSettings: { + customEmailAddresses: [ + 'test.user@testcompany.com' ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + locale: 'en-US' + sendToOwners: 'Send' } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - managedIdentities: { - systemAssigned: true - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } ] - } - privateEndpoints: [ - { - ipConfigurations: [ - { - name: 'myIpConfig-1' - properties: { - groupId: 'AzureSiteRecovery' - memberName: 'SiteRecovery-tel1' - privateIPAddress: '10.0.0.10' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + privateEndpoints: [ + { + ipConfigurations: [ + { + name: 'myIpConfig-1' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-tel1' + privateIPAddress: '10.0.0.10' + } } - } - { - name: 'myIPconfig-2' - properties: { - groupId: 'AzureSiteRecovery' - memberName: 'SiteRecovery-prot2' - privateIPAddress: '10.0.0.11' + { + name: 'myIPconfig-2' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-prot2' + privateIPAddress: '10.0.0.11' + } } - } - { - name: 'myIPconfig-3' - properties: { - groupId: 'AzureSiteRecovery' - memberName: 'SiteRecovery-srs1' - privateIPAddress: '10.0.0.12' + { + name: 'myIPconfig-3' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-srs1' + privateIPAddress: '10.0.0.12' + } } - } - { - name: 'myIPconfig-4' - properties: { - groupId: 'AzureSiteRecovery' - memberName: 'SiteRecovery-rcm1' - privateIPAddress: '10.0.0.13' + { + name: 'myIPconfig-4' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-rcm1' + privateIPAddress: '10.0.0.13' + } } - } - { - name: 'myIPconfig-5' - properties: { - groupId: 'AzureSiteRecovery' - memberName: 'SiteRecovery-id1' - privateIPAddress: '10.0.0.14' + { + name: 'myIPconfig-5' + properties: { + groupId: 'AzureSiteRecovery' + memberName: 'SiteRecovery-id1' + privateIPAddress: '10.0.0.14' + } } + ] + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + } + ] + monitoringSettings: { + azureMonitorAlertSettings: { + alertsForAllJobFailures: 'Enabled' + } + classicAlertSettings: { + alertsForCriticalOperations: 'Enabled' } } - ] - monitoringSettings: { - azureMonitorAlertSettings: { - alertsForAllJobFailures: 'Enabled' - } - classicAlertSettings: { - alertsForCriticalOperations: 'Enabled' + securitySettings: { + immutabilitySettings: { + state: 'Unlocked' + } } - } - securitySettings: { - immutabilitySettings: { - state: 'Unlocked' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } } -}] +] diff --git a/avm/res/resource-graph/query/main.bicep b/avm/res/resource-graph/query/main.bicep index c5e14f413c..d80d1dcd9d 100644 --- a/avm/res/resource-graph/query/main.bicep +++ b/avm/res/resource-graph/query/main.bicep @@ -38,40 +38,50 @@ 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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 // // ================ // -resource rgQuery_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.' +resource rgQuery_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: rgQuery } - scope: rgQuery -} -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.resourcegraph-query.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.resourcegraph-query.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource rgQuery 'Microsoft.ResourceGraph/queries@2018-09-01-preview' = { name: name @@ -83,19 +93,25 @@ resource rgQuery 'Microsoft.ResourceGraph/queries@2018-09-01-preview' = { } } -resource rgQuery_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(rgQuery.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource rgQuery_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(rgQuery.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: rgQuery } - scope: rgQuery -}] +] // ================ // // Outputs // diff --git a/avm/res/resource-graph/query/main.json b/avm/res/resource-graph/query/main.json index c83a3bcccc..e4cd74859c 100644 --- a/avm/res/resource-graph/query/main.json +++ b/avm/res/resource-graph/query/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11608089387685875892" + "version": "0.26.54.24096", + "templateHash": "9585256428416945935" }, "name": "Resource Graph Queries", "description": "This module deploys a Resource Graph Query.", diff --git a/avm/res/resource-graph/query/tests/e2e/max/main.test.bicep b/avm/res/resource-graph/query/tests/e2e/max/main.test.bicep index 3f7e8edead..d5075817e7 100644 --- a/avm/res/resource-graph/query/tests/e2e/max/main.test.bicep +++ b/avm/res/resource-graph/query/tests/e2e/max/main.test.bicep @@ -65,7 +65,10 @@ module testDeployment '../../../main.bicep' = { principalType: 'ServicePrincipal' } { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) principalId: nestedDependencies.outputs.managedIdentityPrincipalId principalType: 'ServicePrincipal' } diff --git a/avm/res/resources/deployment-script/main.bicep b/avm/res/resources/deployment-script/main.bicep index 0a6d1f7a51..262a54aea0 100644 --- a/avm/res/resources/deployment-script/main.bicep +++ b/avm/res/resources/deployment-script/main.bicep @@ -92,80 +92,110 @@ 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -var subnetIds = [for subnetResourceId in (subnetResourceIds ?? []): { - id: subnetResourceId -}] +var subnetIds = [ + for subnetResourceId in (subnetResourceIds ?? []): { + id: subnetResourceId + } +] var containerSettings = { containerGroupName: containerGroupName subnetIds: !empty(subnetIds ?? []) ? subnetIds : null } -var formattedUserAssignedIdentities = reduce(map((managedIdentities.?userAssignedResourcesIds ?? []), (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 - userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null -} : null +var formattedUserAssignedIdentities = reduce( + map((managedIdentities.?userAssignedResourcesIds ?? []), (id) => { '${id}': {} }), + {}, + (cur, next) => union(cur, next) +) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } -resource storageAccount 'Microsoft.Storage/storageAccounts@2021-04-01' existing = if (!empty(storageAccountResourceId)) { - name: last(split((!empty(storageAccountResourceId) ? storageAccountResourceId : 'dummyAccount'), '/'))! - scope: resourceGroup(split((!empty(storageAccountResourceId) ? storageAccountResourceId : '//'), '/')[2], split((!empty(storageAccountResourceId) ? storageAccountResourceId : '////'), '/')[4]) -} +var identity = !empty(managedIdentities) + ? { + type: !empty(managedIdentities.?userAssignedResourcesIds ?? {}) ? 'UserAssigned' : null + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null + } + : null + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-04-01' existing = + if (!empty(storageAccountResourceId)) { + name: last(split((!empty(storageAccountResourceId) ? storageAccountResourceId : 'dummyAccount'), '/'))! + scope: resourceGroup( + split((!empty(storageAccountResourceId) ? storageAccountResourceId : '//'), '/')[2], + split((!empty(storageAccountResourceId) ? storageAccountResourceId : '////'), '/')[4] + ) + } -var storageAccountSettings = !empty(storageAccountResourceId) ? { - storageAccountKey: empty(subnetResourceIds) ? listKeys(storageAccount.id, '2023-01-01').keys[0].value : null - storageAccountName: last(split(storageAccountResourceId, '/')) -} : null +var storageAccountSettings = !empty(storageAccountResourceId) + ? { + storageAccountKey: empty(subnetResourceIds) ? listKeys(storageAccount.id, '2023-01-01').keys[0].value : null + storageAccountName: last(split(storageAccountResourceId, '/')) + } + : null // ============ // // Dependencies // // ============ // -resource deploymentScript_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.' +resource deploymentScript_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: deploymentScript } - scope: deploymentScript -} -resource deploymentScript_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(deploymentScript.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource deploymentScript_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(deploymentScript.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: deploymentScript } - scope: deploymentScript -}] - -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.resources-deploymentscript.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +] + +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.resources-deploymentscript.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} // ================ // // Resources // diff --git a/avm/res/resources/deployment-script/main.json b/avm/res/resources/deployment-script/main.json index 4001d00487..7e14a29e6d 100644 --- a/avm/res/resources/deployment-script/main.json +++ b/avm/res/resources/deployment-script/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11832942286479289748" + "version": "0.26.54.24096", + "templateHash": "6519455487255292674" }, "name": "Deployment Scripts", "description": "This module deploys Deployment Scripts.", 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 7e327c6e68..9af8441a2c 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 @@ -94,7 +94,10 @@ module testDeployment '../../../main.bicep' = { principalType: 'ServicePrincipal' } { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) principalId: nestedDependencies.outputs.managedIdentityPrincipalId principalType: 'ServicePrincipal' } diff --git a/avm/res/resources/resource-group/main.bicep b/avm/res/resources/resource-group/main.bicep index aba3a31722..70c3c63f76 100644 --- a/avm/res/resources/resource-group/main.bicep +++ b/avm/res/resources/resource-group/main.bicep @@ -22,24 +22,25 @@ param tags object? @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.resources-resourcegroup.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - location: location - 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' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.resources-resourcegroup.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + location: location + 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' + } } } } } -} resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { location: location @@ -49,22 +50,24 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { properties: {} } -module resourceGroup_lock 'modules/nested_lock.bicep' = if (!empty(lock ?? {}) && lock.?kind != 'None') { - name: '${uniqueString(deployment().name, location)}-RG-Lock' - params: { - lock: lock - name: resourceGroup.name +module resourceGroup_lock 'modules/nested_lock.bicep' = + if (!empty(lock ?? {}) && lock.?kind != 'None') { + name: '${uniqueString(deployment().name, location)}-RG-Lock' + params: { + lock: lock + name: resourceGroup.name + } + scope: resourceGroup } - scope: resourceGroup -} -module resourceGroup_roleAssignments 'modules/nested_roleAssignments.bicep' = if (!empty(roleAssignments ?? [])) { - name: '${uniqueString(deployment().name, location)}-RG-RoleAssignments' - params: { - roleAssignments: roleAssignments +module resourceGroup_roleAssignments 'modules/nested_roleAssignments.bicep' = + if (!empty(roleAssignments ?? [])) { + name: '${uniqueString(deployment().name, location)}-RG-RoleAssignments' + params: { + roleAssignments: roleAssignments + } + scope: resourceGroup } - scope: resourceGroup -} @description('The name of the resource group.') output name string = resourceGroup.name diff --git a/avm/res/resources/resource-group/main.json b/avm/res/resources/resource-group/main.json index 0a38a86917..8a95c3e2fc 100644 --- a/avm/res/resources/resource-group/main.json +++ b/avm/res/resources/resource-group/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4726997439042123327" + "version": "0.26.54.24096", + "templateHash": "13773232964847117245" }, "name": "Resource Groups", "description": "This module deploys a Resource Group.", @@ -202,8 +202,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "7668050384482764751" + "version": "0.26.54.24096", + "templateHash": "1401075311163527928" } }, "definitions": { @@ -288,8 +288,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3156241559834375483" + "version": "0.26.54.24096", + "templateHash": "5825198357776663348" } }, "definitions": { diff --git a/avm/res/resources/resource-group/tests/e2e/defaults/main.test.bicep b/avm/res/resources/resource-group/tests/e2e/defaults/main.test.bicep index 63ad08354a..265479917f 100644 --- a/avm/res/resources/resource-group/tests/e2e/defaults/main.test.bicep +++ b/avm/res/resources/resource-group/tests/e2e/defaults/main.test.bicep @@ -21,10 +21,12 @@ param namePrefix string = '#_namePrefix_#' // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - name: 'avm-${namePrefix}-resources.resourcegroups-${serviceShort}-rg' - location: resourceLocation +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: 'avm-${namePrefix}-resources.resourcegroups-${serviceShort}-rg' + location: resourceLocation + } } -}] +] diff --git a/avm/res/resources/resource-group/tests/e2e/max/main.test.bicep b/avm/res/resources/resource-group/tests/e2e/max/main.test.bicep index 08e5060ba4..37a96bfff5 100644 --- a/avm/res/resources/resource-group/tests/e2e/max/main.test.bicep +++ b/avm/res/resources/resource-group/tests/e2e/max/main.test.bicep @@ -65,7 +65,10 @@ module testDeployment '../../../main.bicep' = { principalType: 'ServicePrincipal' } { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) principalId: nestedDependencies.outputs.managedIdentityPrincipalId principalType: 'ServicePrincipal' } diff --git a/avm/res/search/search-service/main.bicep b/avm/res/search/search-service/main.bicep index 3ad29c9c68..3325879f8a 100644 --- a/avm/res/search/search-service/main.bicep +++ b/avm/res/search/search-service/main.bicep @@ -101,9 +101,11 @@ param tags object? // Variables // // ============= // -var identity = !empty(managedIdentities) ? { - type: (managedIdentities.?systemAssigned ?? false) ? 'SystemAssigned' : 'None' -} : null +var identity = !empty(managedIdentities) + ? { + type: (managedIdentities.?systemAssigned ?? false) ? 'SystemAssigned' : 'None' + } + : null // =============== // // Deployments // @@ -113,30 +115,46 @@ 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'Search Index Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8ebe5a00-799e-43f5-93ac-243d3dce84a7') - 'Search Index Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1407120a-92aa-4202-b7e9-c0e197c71c8f') - 'Search Service Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7ca78c08-252a-4471-8644-bb5ff32d4ba0') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' + ) + 'Search Index Data Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '8ebe5a00-799e-43f5-93ac-243d3dce84a7' + ) + 'Search Index Data Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '1407120a-92aa-4202-b7e9-c0e197c71c8f' + ) + 'Search Service Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '7ca78c08-252a-4471-8644-bb5ff32d4ba0' + ) + 'User Access Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.search-searchservice.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.search-searchservice.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource searchService 'Microsoft.Search/searchServices@2023-11-01' = { location: location @@ -161,109 +179,138 @@ resource searchService 'Microsoft.Search/searchServices@2023-11-01' = { } } -resource searchService_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource searchService_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: searchService } - scope: searchService -}] +] -resource searchService_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.' +resource searchService_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: searchService } - scope: searchService -} -resource searchService_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(searchService.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource searchService_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(searchService.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: searchService } - scope: searchService -}] - -module searchService_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-SearchService-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(searchService.id, '/'))}-${privateEndpoint.?service ?? 'searchService'}-${index}' - privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(searchService.id, '/'))}-${privateEndpoint.?service ?? 'searchService'}-${index}' - properties: { - privateLinkServiceId: searchService.id - groupIds: [ - privateEndpoint.?service ?? 'searchService' +] + +module searchService_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-SearchService-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(searchService.id, '/'))}-${privateEndpoint.?service ?? 'searchService'}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(searchService.id, '/'))}-${privateEndpoint.?service ?? 'searchService'}-${index}' + properties: { + privateLinkServiceId: searchService.id + groupIds: [ + privateEndpoint.?service ?? 'searchService' + ] + } + } ] - } - } - ] : null - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(searchService.id, '/'))}-${privateEndpoint.?service ?? 'searchService'}-${index}' - properties: { - privateLinkServiceId: searchService.id - groupIds: [ - privateEndpoint.?service ?? 'searchService' + : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(searchService.id, '/'))}-${privateEndpoint.?service ?? 'searchService'}-${index}' + properties: { + privateLinkServiceId: searchService.id + groupIds: [ + privateEndpoint.?service ?? 'searchService' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] +] // The Shared Private Link Resources must be deployed sequentially // otherwise the deployment may fail. // Using batchSize(1) to deploy them one by one @batchSize(1) -module searchService_sharedPrivateLinkResources 'shared-private-link-resource/main.bicep' = [for (sharedPrivateLinkResource, index) in sharedPrivateLinkResources: { - name: '${uniqueString(deployment().name, location)}-searchService-SharedPrivateLink-${index}' - params: { - name: contains(sharedPrivateLinkResource, 'name') ? sharedPrivateLinkResource.name : 'spl-${last(split(searchService.id, '/'))}-${sharedPrivateLinkResource.groupId}-${index}' - searchServiceName: searchService.name - privateLinkResourceId: sharedPrivateLinkResource.privateLinkResourceId - groupId: sharedPrivateLinkResource.groupId - requestMessage: sharedPrivateLinkResource.requestMessage - resourceRegion: sharedPrivateLinkResource.?resourceRegion +module searchService_sharedPrivateLinkResources 'shared-private-link-resource/main.bicep' = [ + for (sharedPrivateLinkResource, index) in sharedPrivateLinkResources: { + name: '${uniqueString(deployment().name, location)}-searchService-SharedPrivateLink-${index}' + params: { + name: contains(sharedPrivateLinkResource, 'name') + ? sharedPrivateLinkResource.name + : 'spl-${last(split(searchService.id, '/'))}-${sharedPrivateLinkResource.groupId}-${index}' + searchServiceName: searchService.name + privateLinkResourceId: sharedPrivateLinkResource.privateLinkResourceId + groupId: sharedPrivateLinkResource.groupId + requestMessage: sharedPrivateLinkResource.requestMessage + resourceRegion: sharedPrivateLinkResource.?resourceRegion + } } -}] +] // =========== // // Outputs // diff --git a/avm/res/search/search-service/main.json b/avm/res/search/search-service/main.json index 742aa10355..6ebfa62b98 100644 --- a/avm/res/search/search-service/main.json +++ b/avm/res/search/search-service/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3319927828453224724" + "version": "0.26.54.24096", + "templateHash": "12548869810736085047" }, "name": "Search Services", "description": "This module deploys a Search Service.", @@ -1424,8 +1424,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "7674026452917741601" + "version": "0.26.54.24096", + "templateHash": "4284041533987186633" }, "name": "Search Services Private Link Resources", "description": "This module deploys a Search Service Private Link Resource.", 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 3532ebe6b0..e6f281a453 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.25.53.49325", - "templateHash": "7674026452917741601" + "version": "0.26.54.24096", + "templateHash": "4284041533987186633" }, "name": "Search Services Private Link Resources", "description": "This module deploys a Search Service Private Link Resource.", 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 bca042441d..c20835fdea 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 @@ -95,7 +95,10 @@ module testDeployment '../../../main.bicep' = { principalType: 'ServicePrincipal' } { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) principalId: nestedDependencies.outputs.managedIdentityPrincipalId principalType: 'ServicePrincipal' } diff --git a/avm/res/service-bus/namespace/authorization-rule/main.json b/avm/res/service-bus/namespace/authorization-rule/main.json index e7f310864e..213b672df5 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.25.53.49325", - "templateHash": "2305438159110957656" + "version": "0.26.54.24096", + "templateHash": "17436716625562680995" }, "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 b3c6887e73..7269a6568a 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.25.53.49325", - "templateHash": "4852834945333619424" + "version": "0.26.54.24096", + "templateHash": "5141733056602320076" }, "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 cfd5c17710..5af577f1e5 100644 --- a/avm/res/service-bus/namespace/main.bicep +++ b/avm/res/service-bus/namespace/main.bicep @@ -95,55 +95,88 @@ 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}': {} }), {}, (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.?userAssignedResourcesIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(managedIdentities.?userAssignedResourcesIds ?? {}) ? 'UserAssigned' : null) - userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null -} : null +var formattedUserAssignedIdentities = reduce( + map((managedIdentities.?userAssignedResourcesIds ?? []), (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.?userAssignedResourcesIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') + : (!empty(managedIdentities.?userAssignedResourcesIds ?? {}) ? 'UserAssigned' : null) + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null + } + : null var 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') - 'Azure Service Bus Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39') + 'Azure Service Bus Data Owner': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '090c5cfd-751d-490a-894a-3ce6f1109419' + ) + 'Azure Service Bus Data Receiver': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0' + ) + 'Azure Service Bus Data Sender': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39' + ) 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.servicebus-namespace.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.servicebus-namespace.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} - -resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId)) { - name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) - scope: resourceGroup(split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4]) - resource cMKKey 'keys@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { - name: customerManagedKey.?keyName ?? 'dummyKey' +resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = + if (!empty(customerManagedKey.?keyVaultResourceId)) { + name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) + scope: resourceGroup( + split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], + split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4] + ) + + resource cMKKey 'keys@2023-02-01' existing = + if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { + name: customerManagedKey.?keyName ?? 'dummyKey' + } } -} -resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { - name: last(split(customerManagedKey.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) - scope: resourceGroup(split((customerManagedKey.?userAssignedIdentityResourceId ?? '//'), '/')[2], split((customerManagedKey.?userAssignedIdentityResourceId ?? '////'), '/')[4]) -} +resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = + if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { + name: last(split(customerManagedKey.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) + scope: resourceGroup( + split((customerManagedKey.?userAssignedIdentityResourceId ?? '//'), '/')[2], + split((customerManagedKey.?userAssignedIdentityResourceId ?? '////'), '/')[4] + ) + } resource serviceBusNamespace 'Microsoft.ServiceBus/namespaces@2022-10-01-preview' = { name: name @@ -155,206 +188,250 @@ resource serviceBusNamespace 'Microsoft.ServiceBus/namespaces@2022-10-01-preview } identity: identity properties: { - publicNetworkAccess: !empty(publicNetworkAccess) ? publicNetworkAccess : (!empty(privateEndpoints) && empty(networkRuleSets) ? 'Disabled' : 'Enabled') + publicNetworkAccess: !empty(publicNetworkAccess) + ? publicNetworkAccess + : (!empty(privateEndpoints) && empty(networkRuleSets) ? 'Disabled' : 'Enabled') minimumTlsVersion: minimumTlsVersion alternateName: alternateName zoneRedundant: zoneRedundant disableLocalAuth: disableLocalAuth premiumMessagingPartitions: skuObject.name == 'Premium' ? premiumMessagingPartitions : 0 - encryption: !empty(customerManagedKey) ? { - keySource: 'Microsoft.KeyVault' - keyVaultProperties: [ - { - identity: !empty(customerManagedKey.?userAssignedIdentityResourceId) ? { - userAssignedIdentity: cMKUserAssignedIdentity.id - } : null - keyName: customerManagedKey!.keyName - keyVaultUri: cMKKeyVault.properties.vaultUri - keyVersion: !empty(customerManagedKey.?keyVersion ?? '') ? customerManagedKey!.keyVersion : last(split(cMKKeyVault::cMKKey.properties.keyUriWithVersion, '/')) + encryption: !empty(customerManagedKey) + ? { + keySource: 'Microsoft.KeyVault' + keyVaultProperties: [ + { + identity: !empty(customerManagedKey.?userAssignedIdentityResourceId) + ? { + userAssignedIdentity: cMKUserAssignedIdentity.id + } + : null + keyName: customerManagedKey!.keyName + keyVaultUri: cMKKeyVault.properties.vaultUri + keyVersion: !empty(customerManagedKey.?keyVersion ?? '') + ? customerManagedKey!.keyVersion + : last(split(cMKKeyVault::cMKKey.properties.keyUriWithVersion, '/')) + } + ] + requireInfrastructureEncryption: requireInfrastructureEncryption } - ] - requireInfrastructureEncryption: requireInfrastructureEncryption - } : null + : null } } -module serviceBusNamespace_authorizationRules 'authorization-rule/main.bicep' = [for (authorizationRule, index) in authorizationRules: { - name: '${uniqueString(deployment().name, location)}-AuthorizationRules-${index}' - params: { - namespaceName: serviceBusNamespace.name - name: authorizationRule.name - rights: authorizationRule.?rights +module serviceBusNamespace_authorizationRules 'authorization-rule/main.bicep' = [ + for (authorizationRule, index) in authorizationRules: { + name: '${uniqueString(deployment().name, location)}-AuthorizationRules-${index}' + params: { + namespaceName: serviceBusNamespace.name + name: authorizationRule.name + rights: authorizationRule.?rights + } } -}] - -module serviceBusNamespace_disasterRecoveryConfig 'disaster-recovery-config/main.bicep' = if (!empty(disasterRecoveryConfig)) { - name: '${uniqueString(deployment().name, location)}-DisasterRecoveryConfig' - params: { - namespaceName: serviceBusNamespace.name - name: disasterRecoveryConfig.?name ?? 'default' - alternateName: disasterRecoveryConfig.?alternateName - partnerNamespaceResourceID: disasterRecoveryConfig.?partnerNamespace +] + +module serviceBusNamespace_disasterRecoveryConfig 'disaster-recovery-config/main.bicep' = + if (!empty(disasterRecoveryConfig)) { + name: '${uniqueString(deployment().name, location)}-DisasterRecoveryConfig' + params: { + namespaceName: serviceBusNamespace.name + name: disasterRecoveryConfig.?name ?? 'default' + alternateName: disasterRecoveryConfig.?alternateName + partnerNamespaceResourceID: disasterRecoveryConfig.?partnerNamespace + } } -} -module serviceBusNamespace_migrationConfigurations 'migration-configuration/main.bicep' = if (!empty(migrationConfiguration ?? {})) { - name: '${uniqueString(deployment().name, location)}-MigrationConfigurations' - params: { - namespaceName: serviceBusNamespace.name - postMigrationName: migrationConfiguration!.postMigrationName - targetNamespaceResourceId: migrationConfiguration!.targetNamespace +module serviceBusNamespace_migrationConfigurations 'migration-configuration/main.bicep' = + if (!empty(migrationConfiguration ?? {})) { + name: '${uniqueString(deployment().name, location)}-MigrationConfigurations' + params: { + namespaceName: serviceBusNamespace.name + postMigrationName: migrationConfiguration!.postMigrationName + targetNamespaceResourceId: migrationConfiguration!.targetNamespace + } } -} -module serviceBusNamespace_networkRuleSet 'network-rule-set/main.bicep' = if (!empty(networkRuleSets) || !empty(privateEndpoints)) { - name: '${uniqueString(deployment().name, location)}-NetworkRuleSet' - params: { - namespaceName: serviceBusNamespace.name - publicNetworkAccess: networkRuleSets.?publicNetworkAccess ?? (!empty(privateEndpoints) && empty(networkRuleSets) ? 'Disabled' : 'Enabled') - defaultAction: networkRuleSets.?defaultAction ?? 'Allow' - trustedServiceAccessEnabled: networkRuleSets.?trustedServiceAccessEnabled ?? true - ipRules: networkRuleSets.?ipRules ?? [] - virtualNetworkRules: networkRuleSets.?virtualNetworkRules ?? [] +module serviceBusNamespace_networkRuleSet 'network-rule-set/main.bicep' = + if (!empty(networkRuleSets) || !empty(privateEndpoints)) { + name: '${uniqueString(deployment().name, location)}-NetworkRuleSet' + params: { + namespaceName: serviceBusNamespace.name + publicNetworkAccess: networkRuleSets.?publicNetworkAccess ?? (!empty(privateEndpoints) && empty(networkRuleSets) + ? 'Disabled' + : 'Enabled') + defaultAction: networkRuleSets.?defaultAction ?? 'Allow' + trustedServiceAccessEnabled: networkRuleSets.?trustedServiceAccessEnabled ?? true + ipRules: networkRuleSets.?ipRules ?? [] + virtualNetworkRules: networkRuleSets.?virtualNetworkRules ?? [] + } } -} -module serviceBusNamespace_queues 'queue/main.bicep' = [for (queue, index) in (queues ?? []): { - name: '${uniqueString(deployment().name, location)}-Queue-${index}' - params: { - namespaceName: serviceBusNamespace.name - name: queue.name - autoDeleteOnIdle: queue.?autoDeleteOnIdle - forwardDeadLetteredMessagesTo: queue.?forwardDeadLetteredMessagesTo - forwardTo: queue.?forwardTo - maxMessageSizeInKilobytes: queue.?maxMessageSizeInKilobytes - authorizationRules: queue.?authorizationRules - deadLetteringOnMessageExpiration: queue.?deadLetteringOnMessageExpiration - defaultMessageTimeToLive: queue.?defaultMessageTimeToLive - duplicateDetectionHistoryTimeWindow: queue.?duplicateDetectionHistoryTimeWindow - enableBatchedOperations: queue.?enableBatchedOperations - enableExpress: queue.?enableExpress - enablePartitioning: queue.?enablePartitioning - lock: queue.?lock ?? lock - lockDuration: queue.?lockDuration - maxDeliveryCount: queue.?maxDeliveryCount - maxSizeInMegabytes: queue.?maxSizeInMegabytes - requiresDuplicateDetection: queue.?requiresDuplicateDetection - requiresSession: queue.?requiresSession - roleAssignments: queue.?roleAssignments - status: queue.?status +module serviceBusNamespace_queues 'queue/main.bicep' = [ + for (queue, index) in (queues ?? []): { + name: '${uniqueString(deployment().name, location)}-Queue-${index}' + params: { + namespaceName: serviceBusNamespace.name + name: queue.name + autoDeleteOnIdle: queue.?autoDeleteOnIdle + forwardDeadLetteredMessagesTo: queue.?forwardDeadLetteredMessagesTo + forwardTo: queue.?forwardTo + maxMessageSizeInKilobytes: queue.?maxMessageSizeInKilobytes + authorizationRules: queue.?authorizationRules + deadLetteringOnMessageExpiration: queue.?deadLetteringOnMessageExpiration + defaultMessageTimeToLive: queue.?defaultMessageTimeToLive + duplicateDetectionHistoryTimeWindow: queue.?duplicateDetectionHistoryTimeWindow + enableBatchedOperations: queue.?enableBatchedOperations + enableExpress: queue.?enableExpress + enablePartitioning: queue.?enablePartitioning + lock: queue.?lock ?? lock + lockDuration: queue.?lockDuration + maxDeliveryCount: queue.?maxDeliveryCount + maxSizeInMegabytes: queue.?maxSizeInMegabytes + requiresDuplicateDetection: queue.?requiresDuplicateDetection + requiresSession: queue.?requiresSession + roleAssignments: queue.?roleAssignments + status: queue.?status + } } -}] - -module serviceBusNamespace_topics 'topic/main.bicep' = [for (topic, index) in (topics ?? []): { - name: '${uniqueString(deployment().name, location)}-Topic-${index}' - params: { - namespaceName: serviceBusNamespace.name - name: topic.name - authorizationRules: topic.?authorizationRules - autoDeleteOnIdle: topic.?autoDeleteOnIdle - defaultMessageTimeToLive: topic.?defaultMessageTimeToLive - duplicateDetectionHistoryTimeWindow: topic.?duplicateDetectionHistoryTimeWindow - enableBatchedOperations: topic.?enableBatchedOperations - enableExpress: topic.?enableExpress - enablePartitioning: topic.?enablePartitioning - lock: topic.?lock ?? lock - maxMessageSizeInKilobytes: topic.?maxMessageSizeInKilobytes - requiresDuplicateDetection: topic.?requiresDuplicateDetection - roleAssignments: topic.?roleAssignments - status: topic.?status - supportOrdering: topic.?supportOrdering - subscriptions: topic.?subscriptions - maxSizeInMegabytes: topic.?maxSizeInMegabytes +] + +module serviceBusNamespace_topics 'topic/main.bicep' = [ + for (topic, index) in (topics ?? []): { + name: '${uniqueString(deployment().name, location)}-Topic-${index}' + params: { + namespaceName: serviceBusNamespace.name + name: topic.name + authorizationRules: topic.?authorizationRules + autoDeleteOnIdle: topic.?autoDeleteOnIdle + defaultMessageTimeToLive: topic.?defaultMessageTimeToLive + duplicateDetectionHistoryTimeWindow: topic.?duplicateDetectionHistoryTimeWindow + enableBatchedOperations: topic.?enableBatchedOperations + enableExpress: topic.?enableExpress + enablePartitioning: topic.?enablePartitioning + lock: topic.?lock ?? lock + maxMessageSizeInKilobytes: topic.?maxMessageSizeInKilobytes + requiresDuplicateDetection: topic.?requiresDuplicateDetection + roleAssignments: topic.?roleAssignments + status: topic.?status + supportOrdering: topic.?supportOrdering + subscriptions: topic.?subscriptions + maxSizeInMegabytes: topic.?maxSizeInMegabytes + } } -}] +] -resource serviceBusNamespace_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.' +resource serviceBusNamespace_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: serviceBusNamespace } - scope: serviceBusNamespace -} -resource serviceBusNamespace_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource serviceBusNamespace_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: serviceBusNamespace } - scope: serviceBusNamespace -}] - -module serviceBusNamespace_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-ServiceBusNamespace-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(serviceBusNamespace.id, '/'))}-${privateEndpoint.?service ?? 'namespace'}-${index}' - privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(serviceBusNamespace.id, '/'))}-${privateEndpoint.?service ?? 'namespace'}-${index}' - properties: { - privateLinkServiceId: serviceBusNamespace.id - groupIds: [ - privateEndpoint.?service ?? 'namespace' +] + +module serviceBusNamespace_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-ServiceBusNamespace-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(serviceBusNamespace.id, '/'))}-${privateEndpoint.?service ?? 'namespace'}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(serviceBusNamespace.id, '/'))}-${privateEndpoint.?service ?? 'namespace'}-${index}' + properties: { + privateLinkServiceId: serviceBusNamespace.id + groupIds: [ + privateEndpoint.?service ?? 'namespace' + ] + } + } ] - } - } - ] : null - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(serviceBusNamespace.id, '/'))}-${privateEndpoint.?service ?? 'namespace'}-${index}' - properties: { - privateLinkServiceId: serviceBusNamespace.id - groupIds: [ - privateEndpoint.?service ?? 'namespace' + : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(serviceBusNamespace.id, '/'))}-${privateEndpoint.?service ?? 'namespace'}-${index}' + properties: { + privateLinkServiceId: serviceBusNamespace.id + groupIds: [ + privateEndpoint.?service ?? 'namespace' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] +] -resource serviceBusNamespace_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(serviceBusNamespace.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource serviceBusNamespace_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(serviceBusNamespace.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: serviceBusNamespace } - scope: serviceBusNamespace -}] +] @description('The resource ID of the deployed service bus namespace.') output resourceId string = serviceBusNamespace.id @@ -667,7 +744,16 @@ type queueType = { 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: ('Active' | 'Disabled' | 'Restoring' | 'SendDisabled' | 'ReceiveDisabled' | 'Creating' | 'Deleting' | 'Renaming' | 'Unknown')? + status: ( + | 'Active' + | 'Disabled' + | 'Restoring' + | 'SendDisabled' + | 'ReceiveDisabled' + | 'Creating' + | 'Deleting' + | 'Renaming' + | 'Unknown')? }[]? type topicType = { @@ -711,7 +797,16 @@ type topicType = { 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: ('Active' | 'Disabled' | 'Restoring' | 'SendDisabled' | 'ReceiveDisabled' | 'Creating' | 'Deleting' | 'Renaming' | 'Unknown')? + status: ( + | 'Active' + | 'Disabled' + | 'Restoring' + | 'SendDisabled' + | 'ReceiveDisabled' + | 'Creating' + | 'Deleting' + | 'Renaming' + | 'Unknown')? @description('Optional. Value that indicates whether the topic supports ordering.') supportOrdering: bool? @@ -770,6 +865,15 @@ type topicType = { 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')? + status: ( + | 'Active' + | 'Disabled' + | 'Restoring' + | 'SendDisabled' + | 'ReceiveDisabled' + | 'Creating' + | 'Deleting' + | 'Renaming' + | 'Unknown')? }[]? }[]? diff --git a/avm/res/service-bus/namespace/main.json b/avm/res/service-bus/namespace/main.json index fc0cee646a..e3ddb14be7 100644 --- a/avm/res/service-bus/namespace/main.json +++ b/avm/res/service-bus/namespace/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11816477645345189868" + "version": "0.26.54.24096", + "templateHash": "9615956004888490264" }, "name": "Service Bus Namespaces", "description": "This module deploys a Service Bus Namespace.", @@ -1454,8 +1454,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2305438159110957656" + "version": "0.26.54.24096", + "templateHash": "17436716625562680995" }, "name": "Service Bus Namespace Authorization Rules", "description": "This module deploys a Service Bus Namespace Authorization Rule.", @@ -1558,8 +1558,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4852834945333619424" + "version": "0.26.54.24096", + "templateHash": "5141733056602320076" }, "name": "Service Bus Namespace Disaster Recovery Configs", "description": "This module deploys a Service Bus Namespace Disaster Recovery Config", @@ -1663,8 +1663,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "7096240042982673427" + "version": "0.26.54.24096", + "templateHash": "15192198614426327006" }, "name": "Service Bus Namespace Migration Configuration", "description": "This module deploys a Service Bus Namespace Migration Configuration.", @@ -1768,8 +1768,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "12312948750335282178" + "version": "0.26.54.24096", + "templateHash": "4933314100479664510" }, "name": "Service Bus Namespace Network Rule Sets", "description": "This module deploys a ServiceBus Namespace Network Rule Set.", @@ -1968,8 +1968,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "1862386755569893710" + "version": "0.26.54.24096", + "templateHash": "5679821968845040041" }, "name": "Service Bus Namespace Queue", "description": "This module deploys a Service Bus Namespace Queue.", @@ -2353,8 +2353,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11143403540623996438" + "version": "0.26.54.24096", + "templateHash": "11000394867797752922" }, "name": "Service Bus Namespace Queue Authorization Rules", "description": "This module deploys a Service Bus Namespace Queue Authorization Rule.", @@ -2534,8 +2534,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "13105717209289706682" + "version": "0.26.54.24096", + "templateHash": "2743713566937430307" }, "name": "Service Bus Namespace Topic", "description": "This module deploys a Service Bus Namespace Topic.", @@ -3017,8 +3017,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "7067820889223773244" + "version": "0.26.54.24096", + "templateHash": "8469884519860433031" }, "name": "Service Bus Namespace Topic Authorization Rules", "description": "This module deploys a Service Bus Namespace Topic Authorization Rule.", @@ -3167,8 +3167,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "10626633836251297018" + "version": "0.26.54.24096", + "templateHash": "14842378053022621119" }, "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 3de44c3b32..5949d14b2e 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.25.53.49325", - "templateHash": "7096240042982673427" + "version": "0.26.54.24096", + "templateHash": "15192198614426327006" }, "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 c65c86e112..ac842a0442 100644 --- a/avm/res/service-bus/namespace/network-rule-set/main.bicep +++ b/avm/res/service-bus/namespace/network-rule-set/main.bicep @@ -30,12 +30,18 @@ param virtualNetworkRules array = [] @description('Optional. List of IpRules. It will not be set if publicNetworkAccess is "Disabled". Otherwise, when used, defaultAction will be set to "Deny".') param ipRules array = [] -var networkRules = [for (virtualNetworkRule, index) in virtualNetworkRules: { - ignoreMissingVnetServiceEndpoint: contains(virtualNetworkRule, 'ignoreMissingVnetServiceEndpoint') ? virtualNetworkRule.ignoreMissingVnetServiceEndpoint : null - subnet: contains(virtualNetworkRule, 'subnetResourceId') ? { - id: virtualNetworkRule.subnetResourceId - } : null -}] +var networkRules = [ + for (virtualNetworkRule, index) in virtualNetworkRules: { + ignoreMissingVnetServiceEndpoint: contains(virtualNetworkRule, 'ignoreMissingVnetServiceEndpoint') + ? virtualNetworkRule.ignoreMissingVnetServiceEndpoint + : null + subnet: contains(virtualNetworkRule, 'subnetResourceId') + ? { + id: virtualNetworkRule.subnetResourceId + } + : null + } +] resource namespace 'Microsoft.ServiceBus/namespaces@2022-10-01-preview' existing = { name: namespaceName @@ -46,7 +52,9 @@ resource networkRuleSet 'Microsoft.ServiceBus/namespaces/networkRuleSets@2022-10 parent: namespace properties: { publicNetworkAccess: publicNetworkAccess - defaultAction: publicNetworkAccess == 'Enabled' ? (!empty(ipRules) || !empty(virtualNetworkRules) ? 'Deny' : defaultAction) : null + defaultAction: publicNetworkAccess == 'Enabled' + ? (!empty(ipRules) || !empty(virtualNetworkRules) ? 'Deny' : defaultAction) + : null trustedServiceAccessEnabled: publicNetworkAccess == 'Enabled' ? trustedServiceAccessEnabled : null ipRules: publicNetworkAccess == 'Enabled' ? ipRules : null virtualNetworkRules: publicNetworkAccess == 'Enabled' ? networkRules : null 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 c7e7350de1..aa8079beeb 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.25.53.49325", - "templateHash": "12312948750335282178" + "version": "0.26.54.24096", + "templateHash": "4933314100479664510" }, "name": "Service Bus Namespace Network Rule Sets", "description": "This module deploys a ServiceBus Namespace Network Rule Set.", 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 46b1f26e50..b343e9a4ef 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.25.53.49325", - "templateHash": "11143403540623996438" + "version": "0.26.54.24096", + "templateHash": "11000394867797752922" }, "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 db033ef614..520bd73926 100644 --- a/avm/res/service-bus/namespace/queue/main.bicep +++ b/avm/res/service-bus/namespace/queue/main.bicep @@ -92,14 +92,29 @@ param lock lockType param roleAssignments roleAssignmentType var 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') - 'Azure Service Bus Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39') + 'Azure Service Bus Data Owner': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '090c5cfd-751d-490a-894a-3ce6f1109419' + ) + 'Azure Service Bus Data Receiver': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0' + ) + 'Azure Service Bus Data Sender': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39' + ) 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } resource namespace 'Microsoft.ServiceBus/namespaces@2022-10-01-preview' existing = { @@ -129,38 +144,49 @@ resource queue 'Microsoft.ServiceBus/namespaces/queues@2022-10-01-preview' = { } } -module queue_authorizationRules 'authorization-rule/main.bicep' = [for (authorizationRule, index) in authorizationRules: { - name: '${deployment().name}-AuthRule-${index}' - params: { - namespaceName: namespaceName - queueName: queue.name - name: authorizationRule.name - rights: authorizationRule.?rights ?? [] +module queue_authorizationRules 'authorization-rule/main.bicep' = [ + for (authorizationRule, index) in authorizationRules: { + name: '${deployment().name}-AuthRule-${index}' + params: { + namespaceName: namespaceName + queueName: queue.name + name: authorizationRule.name + rights: authorizationRule.?rights ?? [] + } } -}] +] -resource queue_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.' +resource queue_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: queue } - scope: queue -} -resource queue_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(queue.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource queue_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(queue.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: queue } - scope: queue -}] +] @description('The name of the deployed queue.') output name string = queue.name diff --git a/avm/res/service-bus/namespace/queue/main.json b/avm/res/service-bus/namespace/queue/main.json index 98b2b87112..bca571c612 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.25.53.49325", - "templateHash": "1862386755569893710" + "version": "0.26.54.24096", + "templateHash": "5679821968845040041" }, "name": "Service Bus Namespace Queue", "description": "This module deploys a Service Bus Namespace Queue.", @@ -390,8 +390,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11143403540623996438" + "version": "0.26.54.24096", + "templateHash": "11000394867797752922" }, "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/defaults/main.test.bicep b/avm/res/service-bus/namespace/tests/e2e/defaults/main.test.bicep index ba24f47f74..3d75b0c635 100644 --- a/avm/res/service-bus/namespace/tests/e2e/defaults/main.test.bicep +++ b/avm/res/service-bus/namespace/tests/e2e/defaults/main.test.bicep @@ -36,14 +36,16 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 - skuObject: { - name: 'Basic' +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 + skuObject: { + name: 'Basic' + } } } -}] +] diff --git a/avm/res/service-bus/namespace/tests/e2e/encr/dependencies.bicep b/avm/res/service-bus/namespace/tests/e2e/encr/dependencies.bicep index 91bcb7661d..5afdae26cd 100644 --- a/avm/res/service-bus/namespace/tests/e2e/encr/dependencies.bicep +++ b/avm/res/service-bus/namespace/tests/e2e/encr/dependencies.bicep @@ -69,7 +69,10 @@ resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { properties: { principalId: managedIdentity.properties.principalId // Key Vault Crypto User - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '12338af0-0e69-4776-bea7-57ae8d297424' + ) principalType: 'ServicePrincipal' } } 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 0d8f78b1fa..9a02d24b0c 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 @@ -51,29 +51,31 @@ 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' - skuObject: { - name: 'Premium' - capacity: 1 - } - location: resourceLocation - managedIdentities: { - systemAssigned: false - userAssignedResourcesIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - customerManagedKey: { - keyName: nestedDependencies.outputs.keyName - keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - userAssignedIdentityResourceId: 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' + skuObject: { + name: 'Premium' + capacity: 1 + } + location: resourceLocation + managedIdentities: { + systemAssigned: false + userAssignedResourcesIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + customerManagedKey: { + keyName: nestedDependencies.outputs.keyName + keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + userAssignedIdentityResourceId: nestedDependencies.outputs.managedIdentityResourceId + } } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] 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 8948e8ae44..a1a500e934 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 @@ -60,205 +60,207 @@ 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' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - location: resourceLocation - skuObject: { - name: 'Premium' - capacity: 16 - } - premiumMessagingPartitions: 1 - zoneRedundant: true - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - - principalType: 'ServicePrincipal' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - networkRuleSets: { - defaultAction: 'Deny' - trustedServiceAccessEnabled: true - virtualNetworkRules: [ - { - ignoreMissingVnetServiceEndpoint: true - subnetResourceId: nestedDependencies.outputs.subnetResourceId - } - ] - ipRules: [ - { - ipMask: '10.0.1.0/32' - action: 'Allow' - } + location: resourceLocation + skuObject: { + name: 'Premium' + capacity: 16 + } + premiumMessagingPartitions: 1 + zoneRedundant: true + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + roleAssignments: [ { - ipMask: '10.0.2.0/32' - action: 'Allow' + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + + principalType: 'ServicePrincipal' } ] - } - authorizationRules: [ - { - name: 'RootManageSharedAccessKey' - rights: [ - 'Listen' - 'Manage' - 'Send' - ] - } - { - name: 'AnotherKey' - rights: [ - 'Listen' - 'Send' - ] - } - ] - queues: [ - { - name: '${namePrefix}${serviceShort}q001' - roleAssignments: [ + networkRuleSets: { + defaultAction: 'Deny' + trustedServiceAccessEnabled: true + virtualNetworkRules: [ { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + ignoreMissingVnetServiceEndpoint: true + subnetResourceId: nestedDependencies.outputs.subnetResourceId } ] - authorizationRules: [ + ipRules: [ { - name: 'RootManageSharedAccessKey' - rights: [ - 'Listen' - 'Manage' - 'Send' - ] + ipMask: '10.0.1.0/32' + action: 'Allow' } { - name: 'AnotherKey' - rights: [ - 'Listen' - 'Send' - ] + ipMask: '10.0.2.0/32' + action: 'Allow' } ] - autoDeleteOnIdle: 'PT5M' - maxMessageSizeInKilobytes: 2048 } - ] - topics: [ - { - name: '${namePrefix}${serviceShort}t001' - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - ] - authorizationRules: [ - { - name: 'RootManageSharedAccessKey' - rights: [ - 'Listen' - 'Manage' - 'Send' - ] - } - { - name: 'AnotherKey' - rights: [ - 'Listen' - 'Send' - ] - } - ] - subscriptions: [ - { - name: 'subscription001' - } - ] - } - ] - diagnosticSettings: [ - { - name: '${namePrefix}-diagnosticsetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - logCategoriesAndGroups: [ - { - category: 'RuntimeAuditLogs' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - privateEndpoints: [ - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + authorizationRules: [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] } - ipConfigurations: [ - { - name: 'myIPconfig' - properties: { - groupId: 'namespace' - memberName: 'namespace' - privateIPAddress: '10.0.0.10' + { + name: 'AnotherKey' + rights: [ + 'Listen' + 'Send' + ] + } + ] + queues: [ + { + name: '${namePrefix}${serviceShort}q001' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' } + ] + authorizationRules: [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + { + name: 'AnotherKey' + rights: [ + 'Listen' + 'Send' + ] + } + ] + autoDeleteOnIdle: 'PT5M' + maxMessageSizeInKilobytes: 2048 + } + ] + topics: [ + { + name: '${namePrefix}${serviceShort}t001' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + authorizationRules: [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + { + name: 'AnotherKey' + rights: [ + 'Listen' + 'Send' + ] + } + ] + subscriptions: [ + { + name: 'subscription001' + } + ] + } + ] + diagnosticSettings: [ + { + name: '${namePrefix}-diagnosticsetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + logCategoriesAndGroups: [ + { + category: 'RuntimeAuditLogs' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + privateEndpoints: [ + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - customDnsConfigs: [ - { - fqdn: 'abc.namespace.com' - ipAddresses: [ - '10.0.0.10' - ] - } - ] - } - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId + ipConfigurations: [ + { + name: 'myIPconfig' + properties: { + groupId: 'namespace' + memberName: 'namespace' + privateIPAddress: '10.0.0.10' + } + } + ] + customDnsConfigs: [ + { + fqdn: 'abc.namespace.com' + ipAddresses: [ + '10.0.0.10' + ] + } + ] + } + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + } + ] + managedIdentities: { + systemAssigned: true + userAssignedResourcesIds: [ + nestedDependencies.outputs.managedIdentityResourceId ] } - ] - managedIdentities: { - systemAssigned: true - userAssignedResourcesIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] + disableLocalAuth: true + publicNetworkAccess: 'Enabled' + minimumTlsVersion: '1.2' } - disableLocalAuth: true - publicNetworkAccess: 'Enabled' - minimumTlsVersion: '1.2' + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - 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 543060cd91..cbd896930d 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 @@ -60,147 +60,149 @@ 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' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - location: resourceLocation - skuObject: { - name: 'Premium' - capacity: 2 - } - premiumMessagingPartitions: 1 - zoneRedundant: true - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - roleAssignments: [] - networkRuleSets: { - defaultAction: 'Deny' - trustedServiceAccessEnabled: true - virtualNetworkRules: [ - { - ignoreMissingVnetServiceEndpoint: true - subnetResourceId: nestedDependencies.outputs.subnetResourceId - } - ] - ipRules: [ - { - ipMask: '10.0.1.0/32' - action: 'Allow' - } - { - ipMask: '10.0.2.0/32' - action: 'Allow' - } - ] - } - authorizationRules: [ - { - name: 'RootManageSharedAccessKey' - rights: [ - 'Listen' - 'Manage' - 'Send' - ] +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - name: 'AnotherKey' - rights: [ - 'Listen' - 'Send' - ] + location: resourceLocation + skuObject: { + name: 'Premium' + capacity: 2 } - ] - queues: [ - { - name: '${namePrefix}${serviceShort}q001' - roleAssignments: [] - authorizationRules: [ - { - name: 'RootManageSharedAccessKey' - rights: [ - 'Listen' - 'Manage' - 'Send' - ] - } + premiumMessagingPartitions: 1 + zoneRedundant: true + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + roleAssignments: [] + networkRuleSets: { + defaultAction: 'Deny' + trustedServiceAccessEnabled: true + virtualNetworkRules: [ { - name: 'AnotherKey' - rights: [ - 'Listen' - 'Send' - ] + ignoreMissingVnetServiceEndpoint: true + subnetResourceId: nestedDependencies.outputs.subnetResourceId } ] - autoDeleteOnIdle: 'PT5M' - maxMessageSizeInKilobytes: 2048 - } - ] - topics: [ - { - name: '${namePrefix}${serviceShort}t001' - roleAssignments: [] - authorizationRules: [ + ipRules: [ { - name: 'RootManageSharedAccessKey' - rights: [ - 'Listen' - 'Manage' - 'Send' - ] + ipMask: '10.0.1.0/32' + action: 'Allow' } { - name: 'AnotherKey' - rights: [ - 'Listen' - 'Send' - ] + ipMask: '10.0.2.0/32' + action: 'Allow' } ] } - ] - diagnosticSettings: [ - { - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - privateEndpoints: [ - { - service: 'namespace' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + authorizationRules: [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + { + name: 'AnotherKey' + rights: [ + 'Listen' + 'Send' + ] + } + ] + queues: [ + { + name: '${namePrefix}${serviceShort}q001' + roleAssignments: [] + authorizationRules: [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + { + name: 'AnotherKey' + rights: [ + 'Listen' + 'Send' + ] + } + ] + autoDeleteOnIdle: 'PT5M' + maxMessageSizeInKilobytes: 2048 } - } - ] - managedIdentities: { - systemAssigned: true - userAssignedResourcesIds: [ - nestedDependencies.outputs.managedIdentityResourceId ] + topics: [ + { + name: '${namePrefix}${serviceShort}t001' + roleAssignments: [] + authorizationRules: [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + { + name: 'AnotherKey' + rights: [ + 'Listen' + 'Send' + ] + } + ] + } + ] + diagnosticSettings: [ + { + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + privateEndpoints: [ + { + service: 'namespace' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + ] + managedIdentities: { + systemAssigned: true + userAssignedResourcesIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + disableLocalAuth: true + publicNetworkAccess: 'Enabled' + minimumTlsVersion: '1.2' } - disableLocalAuth: true - publicNetworkAccess: 'Enabled' - minimumTlsVersion: '1.2' + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] 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 104532158b..b2ba653765 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.25.53.49325", - "templateHash": "7067820889223773244" + "version": "0.26.54.24096", + "templateHash": "8469884519860433031" }, "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 1262f6baae..aafb8dfc01 100644 --- a/avm/res/service-bus/namespace/topic/main.bicep +++ b/avm/res/service-bus/namespace/topic/main.bicep @@ -80,14 +80,29 @@ param roleAssignments roleAssignmentType param subscriptions array = [] var 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') - 'Azure Service Bus Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39') + 'Azure Service Bus Data Owner': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '090c5cfd-751d-490a-894a-3ce6f1109419' + ) + 'Azure Service Bus Data Receiver': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0' + ) + 'Azure Service Bus Data Sender': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39' + ) 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } resource namespace 'Microsoft.ServiceBus/namespaces@2022-10-01-preview' existing = { @@ -97,7 +112,8 @@ resource namespace 'Microsoft.ServiceBus/namespaces@2022-10-01-preview' existing resource topic 'Microsoft.ServiceBus/namespaces/topics@2022-10-01-preview' = { name: name parent: namespace - properties: union({ + properties: union( + { autoDeleteOnIdle: autoDeleteOnIdle defaultMessageTimeToLive: defaultMessageTimeToLive duplicateDetectionHistoryTimeWindow: duplicateDetectionHistoryTimeWindow @@ -107,67 +123,84 @@ resource topic 'Microsoft.ServiceBus/namespaces/topics@2022-10-01-preview' = { status: status supportOrdering: supportOrdering maxSizeInMegabytes: maxSizeInMegabytes - }, (namespace.sku.name == 'Premium') ? { - enableExpress: enableExpress - maxMessageSizeInKilobytes: maxMessageSizeInKilobytes - } : {}) + }, + (namespace.sku.name == 'Premium') + ? { + enableExpress: enableExpress + maxMessageSizeInKilobytes: maxMessageSizeInKilobytes + } + : {} + ) } -module topic_authorizationRules 'authorization-rule/main.bicep' = [for (authorizationRule, index) in authorizationRules: { - name: '${deployment().name}-AuthRule-${index}' - params: { - namespaceName: namespaceName - topicName: topic.name - name: authorizationRule.name - rights: contains(authorizationRule, 'rights') ? authorizationRule.rights : [] +module topic_authorizationRules 'authorization-rule/main.bicep' = [ + for (authorizationRule, index) in authorizationRules: { + name: '${deployment().name}-AuthRule-${index}' + params: { + namespaceName: namespaceName + topicName: topic.name + name: authorizationRule.name + rights: contains(authorizationRule, 'rights') ? authorizationRule.rights : [] + } } -}] +] -resource topic_lock 'Microsoft.Authorization/locks@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.' +resource topic_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: topic } - scope: topic -} -resource topic_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(topic.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource topic_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(topic.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: topic } - scope: topic -}] - -module topic_subscription 'subscription/main.bicep' = [for (subscription, index) in (subscriptions ?? []): { - name: '${deployment().name}-subscription-${index}' - params: { - name: subscription.name - namespaceName: namespace.name - topicName: topic.name - autoDeleteOnIdle: subscription.?autoDeleteOnIdle ?? 'PT1H' - defaultMessageTimeToLive: subscription.?defaultMessageTimeToLive ?? 'P14D' - duplicateDetectionHistoryTimeWindow: subscription.?duplicateDetectionHistoryTimeWindow ?? 'PT10M' - enableBatchedOperations: subscription.?enableBatchedOperations ?? true - clientAffineProperties: subscription.?clientAffineProperties ?? {} - deadLetteringOnFilterEvaluationExceptions: subscription.?deadLetteringOnFilterEvaluationExceptions ?? true - deadLetteringOnMessageExpiration: subscription.?deadLetteringOnMessageExpiration ?? false - forwardDeadLetteredMessagesTo: subscription.?forwardDeadLetteredMessagesTo - forwardTo: subscription.?forwardTo - isClientAffine: subscription.?isClientAffine ?? false - lockDuration: subscription.?lockDuration ?? 'PT1M' - maxDeliveryCount: subscription.?maxDeliveryCount ?? 10 - requiresSession: subscription.?requiresSession ?? false - status: subscription.?status ?? 'Active' +] + +module topic_subscription 'subscription/main.bicep' = [ + for (subscription, index) in (subscriptions ?? []): { + name: '${deployment().name}-subscription-${index}' + params: { + name: subscription.name + namespaceName: namespace.name + topicName: topic.name + autoDeleteOnIdle: subscription.?autoDeleteOnIdle ?? 'PT1H' + defaultMessageTimeToLive: subscription.?defaultMessageTimeToLive ?? 'P14D' + duplicateDetectionHistoryTimeWindow: subscription.?duplicateDetectionHistoryTimeWindow ?? 'PT10M' + enableBatchedOperations: subscription.?enableBatchedOperations ?? true + clientAffineProperties: subscription.?clientAffineProperties ?? {} + deadLetteringOnFilterEvaluationExceptions: subscription.?deadLetteringOnFilterEvaluationExceptions ?? true + deadLetteringOnMessageExpiration: subscription.?deadLetteringOnMessageExpiration ?? false + forwardDeadLetteredMessagesTo: subscription.?forwardDeadLetteredMessagesTo + forwardTo: subscription.?forwardTo + isClientAffine: subscription.?isClientAffine ?? false + lockDuration: subscription.?lockDuration ?? 'PT1M' + maxDeliveryCount: subscription.?maxDeliveryCount ?? 10 + requiresSession: subscription.?requiresSession ?? false + status: subscription.?status ?? 'Active' + } } -}] +] @description('The name of the deployed topic.') output name string = topic.name @@ -266,5 +299,14 @@ type subscriptionsType = { 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')? + status: ( + | 'Active' + | 'Disabled' + | 'Restoring' + | 'SendDisabled' + | 'ReceiveDisabled' + | 'Creating' + | 'Deleting' + | 'Renaming' + | 'Unknown')? }[]? diff --git a/avm/res/service-bus/namespace/topic/main.json b/avm/res/service-bus/namespace/topic/main.json index ed97a90dcd..1bbf1eca82 100644 --- a/avm/res/service-bus/namespace/topic/main.json +++ b/avm/res/service-bus/namespace/topic/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "13105717209289706682" + "version": "0.26.54.24096", + "templateHash": "2743713566937430307" }, "name": "Service Bus Namespace Topic", "description": "This module deploys a Service Bus Namespace Topic.", @@ -488,8 +488,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "7067820889223773244" + "version": "0.26.54.24096", + "templateHash": "8469884519860433031" }, "name": "Service Bus Namespace Topic Authorization Rules", "description": "This module deploys a Service Bus Namespace Topic Authorization Rule.", @@ -638,8 +638,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "10626633836251297018" + "version": "0.26.54.24096", + "templateHash": "14842378053022621119" }, "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 ae24b1d16b..3e87e184d8 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.25.53.49325", - "templateHash": "10626633836251297018" + "version": "0.26.54.24096", + "templateHash": "14842378053022621119" }, "name": "Service Bus Namespace Topic Subscription", "description": "This module deploys a Service Bus Namespace Topic Subscription.", diff --git a/avm/res/signal-r-service/signal-r/main.bicep b/avm/res/signal-r-service/signal-r/main.bicep index 9e0509c365..6cd2b791ba 100644 --- a/avm/res/signal-r-service/signal-r/main.bicep +++ b/avm/res/signal-r-service/signal-r/main.bicep @@ -33,7 +33,9 @@ param sku string = 'Standard_S1' 'Standard' ]) @description('Optional. The tier of the service.') -param tier string = sku == 'Free_F1' ? 'Free' : sku == 'Standard_S1' || sku == 'Standard_S2' || sku == 'Standard_S3' ? 'Standard' : 'Premium' +param tier string = sku == 'Free_F1' + ? 'Free' + : sku == 'Standard_S1' || sku == 'Standard_S2' || sku == 'Standard_S3' ? 'Standard' : 'Premium' @description('Optional. The unit count of the resource.') param capacity int = 1 @@ -108,49 +110,84 @@ param roleAssignments roleAssignmentType @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -var liveTraceCatagories = [for configuration in liveTraceCatagoriesToEnable: { - name: configuration - enabled: 'true' -}] +var liveTraceCatagories = [ + for configuration in liveTraceCatagoriesToEnable: { + name: configuration + enabled: 'true' + } +] -var resourceLogConfiguration = [for configuration in resourceLogConfigurationsToEnable: { - name: configuration - enabled: 'true' -}] +var resourceLogConfiguration = [ + for configuration in resourceLogConfigurationsToEnable: { + name: configuration + enabled: 'true' + } +] 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'SignalR AccessKey Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '04165923-9d83-45d5-8227-78b77b0a687e') - 'SignalR App Server': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '420fcaa2-552c-430f-98ca-3264be4806c7') - 'SignalR REST API Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd53cd77-2268-407a-8f46-7e7863d0f521') - 'SignalR REST API Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ddde6b66-c0df-4114-a159-3618637b3035') - 'SignalR Service Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7e4f1700-ea5a-4f59-8f37-079cfe29dce3') - 'SignalR/Web PubSub Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') - 'Web PubSub Service Owner (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12cf5a90-567b-43ae-8102-96cf46c7d9b4') - 'Web PubSub Service Reader (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bfb1c7d2-fb1a-466b-b2ba-aee63b92deaf') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' + ) + 'SignalR AccessKey Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '04165923-9d83-45d5-8227-78b77b0a687e' + ) + 'SignalR App Server': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '420fcaa2-552c-430f-98ca-3264be4806c7' + ) + 'SignalR REST API Owner': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'fd53cd77-2268-407a-8f46-7e7863d0f521' + ) + 'SignalR REST API Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'ddde6b66-c0df-4114-a159-3618637b3035' + ) + 'SignalR Service Owner': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '7e4f1700-ea5a-4f59-8f37-079cfe29dce3' + ) + 'SignalR/Web PubSub Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761' + ) + 'User Access Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + ) + 'Web PubSub Service Owner (Preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '12cf5a90-567b-43ae-8102-96cf46c7d9b4' + ) + 'Web PubSub Service Reader (Preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'bfb1c7d2-fb1a-466b-b2ba-aee63b92deaf' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.signalrservice-signalr.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.signalrservice-signalr.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource signalR 'Microsoft.SignalRService/signalR@2022-02-01' = { name: name @@ -169,87 +206,112 @@ resource signalR 'Microsoft.SignalRService/signalR@2022-02-01' = { disableAadAuth: disableAadAuth disableLocalAuth: disableLocalAuth features: features - liveTraceConfiguration: !empty(liveTraceCatagoriesToEnable) ? { - categories: liveTraceCatagories - } : {} + liveTraceConfiguration: !empty(liveTraceCatagoriesToEnable) + ? { + categories: liveTraceCatagories + } + : {} networkACLs: !empty(networkAcls) ? any(networkAcls) : null - publicNetworkAccess: !empty(publicNetworkAccess) ? any(publicNetworkAccess) : (!empty(privateEndpoints) && empty(networkAcls) ? 'Disabled' : null) + publicNetworkAccess: !empty(publicNetworkAccess) + ? any(publicNetworkAccess) + : (!empty(privateEndpoints) && empty(networkAcls) ? 'Disabled' : null) resourceLogConfiguration: { categories: resourceLogConfiguration } tls: { clientCertEnabled: clientCertEnabled } - upstream: !empty(upstreamTemplatesToEnable) ? { - templates: upstreamTemplatesToEnable - } : {} + upstream: !empty(upstreamTemplatesToEnable) + ? { + templates: upstreamTemplatesToEnable + } + : {} } } -module signalR_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.1' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-signalR-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(signalR.id, '/'))}-${privateEndpoint.?service ?? 'signalr'}-${index}' - privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(signalR.id, '/'))}-${privateEndpoint.?service ?? 'signalr'}-${index}' - properties: { - privateLinkServiceId: signalR.id - groupIds: [ - privateEndpoint.?service ?? 'signalr' +module signalR_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.1' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-signalR-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(signalR.id, '/'))}-${privateEndpoint.?service ?? 'signalr'}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(signalR.id, '/'))}-${privateEndpoint.?service ?? 'signalr'}-${index}' + properties: { + privateLinkServiceId: signalR.id + groupIds: [ + privateEndpoint.?service ?? 'signalr' + ] + } + } ] - } - } - ] : null - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(signalR.id, '/'))}-${privateEndpoint.?service ?? 'signalr'}-${index}' - properties: { - privateLinkServiceId: signalR.id - groupIds: [ - privateEndpoint.?service ?? 'signalr' + : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(signalR.id, '/'))}-${privateEndpoint.?service ?? 'signalr'}-${index}' + properties: { + privateLinkServiceId: signalR.id + groupIds: [ + privateEndpoint.?service ?? 'signalr' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] +] -resource signalR_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.' +resource signalR_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: signalR } - scope: signalR -} -resource signalR_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(signalR.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource signalR_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(signalR.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: signalR } - scope: signalR -}] +] @description('The SignalR name.') output name string = signalR.name diff --git a/avm/res/signal-r-service/signal-r/main.json b/avm/res/signal-r-service/signal-r/main.json index cdf2a9c339..4a39843b52 100644 --- a/avm/res/signal-r-service/signal-r/main.json +++ b/avm/res/signal-r-service/signal-r/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "12709667084412433453" + "version": "0.26.54.24096", + "templateHash": "4485935239460152406" }, "name": "SignalR Service SignalR", "description": "This module deploys a SignalR Service SignalR.", 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 eb83b896b0..8f4198f941 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 @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 +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 + } } -}] +] 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 ea3760d496..21e8ab2c5b 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 @@ -46,89 +46,93 @@ 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 - capacity: 2 - clientCertEnabled: false - disableAadAuth: false - disableLocalAuth: true - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - kind: 'SignalR' - networkAcls: { - defaultAction: 'Allow' - privateEndpoints: [ - { +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 + capacity: 2 + clientCertEnabled: false + disableAadAuth: false + disableLocalAuth: true + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + kind: 'SignalR' + networkAcls: { + defaultAction: 'Allow' + privateEndpoints: [ + { + allow: [] + deny: [ + 'ServerConnection' + 'Trace' + ] + name: 'pe-${namePrefix}-${serviceShort}-001' + } + ] + publicNetwork: { allow: [] deny: [ - 'ServerConnection' + 'RESTAPI' 'Trace' ] - name: 'pe-${namePrefix}-${serviceShort}-001' - } - ] - publicNetwork: { - allow: [] - deny: [ - 'RESTAPI' - 'Trace' - ] } - } - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + } + ] + resourceLogConfigurationsToEnable: [ + 'ConnectivityLogs' + ] + 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' + } + ] + sku: 'Standard_S1' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId - } - ] - resourceLogConfigurationsToEnable: [ - 'ConnectivityLogs' - ] - 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' - } - ] - sku: 'Standard_S1' - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] 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 14a5ab8f7c..51ca8dd306 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 @@ -45,62 +45,63 @@ 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 - capacity: 2 - clientCertEnabled: false - disableAadAuth: false - disableLocalAuth: true - kind: 'SignalR' - networkAcls: { - defaultAction: 'Allow' - privateEndpoints: [ - { +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 + capacity: 2 + clientCertEnabled: false + disableAadAuth: false + disableLocalAuth: true + kind: 'SignalR' + networkAcls: { + defaultAction: 'Allow' + privateEndpoints: [ + { + allow: [] + deny: [ + 'ServerConnection' + 'Trace' + ] + name: 'pe-${namePrefix}-${serviceShort}-001' + } + ] + publicNetwork: { allow: [] deny: [ - 'ServerConnection' + 'RESTAPI' 'Trace' ] - name: 'pe-${namePrefix}-${serviceShort}-001' - } - ] - publicNetwork: { - allow: [] - deny: [ - 'RESTAPI' - 'Trace' - ] } - } - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } + ] + resourceLogConfigurationsToEnable: [ + 'ConnectivityLogs' + ] + sku: 'Standard_S1' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - resourceLogConfigurationsToEnable: [ - 'ConnectivityLogs' - ] - sku: 'Standard_S1' - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] 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 32b0b0252f..54ad065a19 100644 --- a/avm/res/signal-r-service/web-pub-sub/main.bicep +++ b/avm/res/signal-r-service/web-pub-sub/main.bicep @@ -65,51 +65,92 @@ param networkAcls object? @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -var resourceLogConfiguration = [for configuration in resourceLogConfigurationsToEnable: { - name: configuration - enabled: 'true' -}] - -var formattedUserAssignedIdentities = reduce(map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), {}, (cur, next) => union(cur, next)) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } +var resourceLogConfiguration = [ + for configuration in resourceLogConfigurationsToEnable: { + name: configuration + enabled: 'true' + } +] -var identity = !empty(managedIdentities) ? { - type: (managedIdentities.?systemAssigned ?? false) ? 'SystemAssigned' : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null) - userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null -} : null +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) + ? 'SystemAssigned' + : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null) + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null + } + : 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'SignalR AccessKey Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '04165923-9d83-45d5-8227-78b77b0a687e') - 'SignalR App Server': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '420fcaa2-552c-430f-98ca-3264be4806c7') - 'SignalR REST API Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd53cd77-2268-407a-8f46-7e7863d0f521') - 'SignalR REST API Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ddde6b66-c0df-4114-a159-3618637b3035') - 'SignalR Service Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7e4f1700-ea5a-4f59-8f37-079cfe29dce3') - 'SignalR/Web PubSub Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') - 'Web PubSub Service Owner (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12cf5a90-567b-43ae-8102-96cf46c7d9b4') - 'Web PubSub Service Reader (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bfb1c7d2-fb1a-466b-b2ba-aee63b92deaf') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' + ) + 'SignalR AccessKey Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '04165923-9d83-45d5-8227-78b77b0a687e' + ) + 'SignalR App Server': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '420fcaa2-552c-430f-98ca-3264be4806c7' + ) + 'SignalR REST API Owner': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'fd53cd77-2268-407a-8f46-7e7863d0f521' + ) + 'SignalR REST API Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'ddde6b66-c0df-4114-a159-3618637b3035' + ) + 'SignalR Service Owner': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '7e4f1700-ea5a-4f59-8f37-079cfe29dce3' + ) + 'SignalR/Web PubSub Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761' + ) + 'User Access Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + ) + 'Web PubSub Service Owner (Preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '12cf5a90-567b-43ae-8102-96cf46c7d9b4' + ) + 'Web PubSub Service Reader (Preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'bfb1c7d2-fb1a-466b-b2ba-aee63b92deaf' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.signalrservice-webpubsub.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.signalrservice-webpubsub.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource webPubSub 'Microsoft.SignalRService/webPubSub@2021-10-01' = { name: name @@ -125,7 +166,9 @@ resource webPubSub 'Microsoft.SignalRService/webPubSub@2021-10-01' = { disableAadAuth: disableAadAuth disableLocalAuth: disableLocalAuth networkACLs: networkAcls - publicNetworkAccess: !empty(publicNetworkAccess) ? any(publicNetworkAccess) : (!empty(privateEndpoints) && empty(networkAcls) ? 'Disabled' : null) + publicNetworkAccess: !empty(publicNetworkAccess) + ? any(publicNetworkAccess) + : (!empty(privateEndpoints) && empty(networkAcls) ? 'Disabled' : null) resourceLogConfiguration: { categories: resourceLogConfiguration } @@ -135,70 +178,89 @@ resource webPubSub 'Microsoft.SignalRService/webPubSub@2021-10-01' = { } } -module webPubSub_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.1' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-webPubSub-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(webPubSub.id, '/'))}-${privateEndpoint.?service ?? 'webpubsub'}-${index}' - privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(webPubSub.id, '/'))}-${privateEndpoint.?service ?? 'webpubsub'}-${index}' - properties: { - privateLinkServiceId: webPubSub.id - groupIds: [ - privateEndpoint.?service ?? 'webpubsub' +module webPubSub_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.1' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-webPubSub-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(webPubSub.id, '/'))}-${privateEndpoint.?service ?? 'webpubsub'}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(webPubSub.id, '/'))}-${privateEndpoint.?service ?? 'webpubsub'}-${index}' + properties: { + privateLinkServiceId: webPubSub.id + groupIds: [ + privateEndpoint.?service ?? 'webpubsub' + ] + } + } ] - } - } - ] : null - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(webPubSub.id, '/'))}-${privateEndpoint.?service ?? 'webpubsub'}-${index}' - properties: { - privateLinkServiceId: webPubSub.id - groupIds: [ - privateEndpoint.?service ?? 'webpubsub' + : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(webPubSub.id, '/'))}-${privateEndpoint.?service ?? 'webpubsub'}-${index}' + properties: { + privateLinkServiceId: webPubSub.id + groupIds: [ + privateEndpoint.?service ?? 'webpubsub' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] +] -resource webPubSub_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.' +resource webPubSub_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: webPubSub } - scope: webPubSub -} -resource webPubSub_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(webPubSub.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource webPubSub_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(webPubSub.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: webPubSub } - scope: webPubSub -}] +] @description('The Web PubSub name.') output name string = webPubSub.name 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 02b172406c..f222512801 100644 --- a/avm/res/signal-r-service/web-pub-sub/main.json +++ b/avm/res/signal-r-service/web-pub-sub/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11458194827556582454" + "version": "0.26.54.24096", + "templateHash": "14787195010509136653" }, "name": "SignalR Web PubSub Services", "description": "This module deploys a SignalR Web PubSub Service.", diff --git a/avm/res/signal-r-service/web-pub-sub/tests/e2e/defaults/main.test.bicep b/avm/res/signal-r-service/web-pub-sub/tests/e2e/defaults/main.test.bicep index 036f4788c4..14e02cb21f 100644 --- a/avm/res/signal-r-service/web-pub-sub/tests/e2e/defaults/main.test.bicep +++ b/avm/res/signal-r-service/web-pub-sub/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 +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 + } } -}] +] diff --git a/avm/res/signal-r-service/web-pub-sub/tests/e2e/max/main.test.bicep b/avm/res/signal-r-service/web-pub-sub/tests/e2e/max/main.test.bicep index 6d921659a0..9d4e07833f 100644 --- a/avm/res/signal-r-service/web-pub-sub/tests/e2e/max/main.test.bicep +++ b/avm/res/signal-r-service/web-pub-sub/tests/e2e/max/main.test.bicep @@ -46,88 +46,93 @@ 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 - capacity: 2 - clientCertEnabled: false - disableAadAuth: false - disableLocalAuth: true - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - networkAcls: { - defaultAction: 'Allow' - privateEndpoints: [ - { +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 + capacity: 2 + clientCertEnabled: false + disableAadAuth: false + disableLocalAuth: true + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + networkAcls: { + defaultAction: 'Allow' + privateEndpoints: [ + { + allow: [] + deny: [ + 'ServerConnection' + 'Trace' + ] + name: 'pe-${namePrefix}-${serviceShort}-001' + } + ] + publicNetwork: { allow: [] deny: [ - 'ServerConnection' + 'RESTAPI' 'Trace' ] - name: 'pe-${namePrefix}-${serviceShort}-001' } - ] - publicNetwork: { - allow: [] - deny: [ - 'RESTAPI' - 'Trace' - ] } - } - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - service: 'webpubsub' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + service: 'webpubsub' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + } + ] + resourceLogConfigurationsToEnable: [ + 'ConnectivityLogs' + ] + 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' + } + ] + sku: 'Standard_S1' + managedIdentities: { + systemAssigned: true } - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId - } - ] - resourceLogConfigurationsToEnable: [ - 'ConnectivityLogs' - ] - 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' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - sku: 'Standard_S1' - managedIdentities: { - systemAssigned: true - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] diff --git a/avm/res/signal-r-service/web-pub-sub/tests/e2e/waf-aligned/main.test.bicep b/avm/res/signal-r-service/web-pub-sub/tests/e2e/waf-aligned/main.test.bicep index 1504efe931..a1ba316a76 100644 --- a/avm/res/signal-r-service/web-pub-sub/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/signal-r-service/web-pub-sub/tests/e2e/waf-aligned/main.test.bicep @@ -45,61 +45,63 @@ 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 - capacity: 2 - clientCertEnabled: false - disableAadAuth: false - disableLocalAuth: true - networkAcls: { - defaultAction: 'Allow' - privateEndpoints: [ - { +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 + capacity: 2 + clientCertEnabled: false + disableAadAuth: false + disableLocalAuth: true + networkAcls: { + defaultAction: 'Allow' + privateEndpoints: [ + { + allow: [] + deny: [ + 'ServerConnection' + 'Trace' + ] + name: 'pe-${namePrefix}-${serviceShort}-001' + } + ] + publicNetwork: { allow: [] deny: [ - 'ServerConnection' + 'RESTAPI' 'Trace' ] - name: 'pe-${namePrefix}-${serviceShort}-001' } - ] - publicNetwork: { - allow: [] - deny: [ - 'RESTAPI' - 'Trace' - ] } - } - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - service: 'webpubsub' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + service: 'webpubsub' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } + ] + resourceLogConfigurationsToEnable: [ + 'ConnectivityLogs' + ] + sku: 'Standard_S1' + managedIdentities: { + systemAssigned: true + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - resourceLogConfigurationsToEnable: [ - 'ConnectivityLogs' - ] - sku: 'Standard_S1' - managedIdentities: { - systemAssigned: true - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } } -}] +] 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 f40030f6d4..b73eaff15f 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 @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17376471861428793697" + "version": "0.26.54.24096", + "templateHash": "13590495271621282724" }, "name": "SQL Server Database Long Term Backup Retention Policies", "description": "This module deploys an Azure SQL Server Database Long-Term Backup Retention Policy.", 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 0aea9d0e91..6ba3e2d233 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.25.53.49325", - "templateHash": "16471212899981632790" + "version": "0.26.54.24096", + "templateHash": "11085405057722780022" }, "name": "Azure SQL Server Database Short Term Backup Retention Policies", "description": "This module deploys an Azure SQL Server Database Short-Term Backup Retention Policy.", diff --git a/avm/res/sql/server/database/main.bicep b/avm/res/sql/server/database/main.bicep index 9a8b4f4a67..f6bc48609e 100644 --- a/avm/res/sql/server/database/main.bicep +++ b/avm/res/sql/server/database/main.bicep @@ -122,16 +122,25 @@ 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({ +var skuVar = union( + { name: skuName tier: skuTier - }, (skuCapacity != null) ? { - capacity: skuCapacity - } : !empty(skuFamily) ? { - family: skuFamily - } : !empty(skuSize) ? { - size: skuSize - } : {}) + }, + (skuCapacity != null) + ? { + capacity: skuCapacity + } + : !empty(skuFamily) + ? { + family: skuFamily + } + : !empty(skuSize) + ? { + size: skuSize + } + : {} +) resource server 'Microsoft.Sql/servers@2022-05-01-preview' existing = { name: serverName @@ -160,42 +169,54 @@ resource database 'Microsoft.Sql/servers/databases@2022-05-01-preview' = { createMode: createMode sourceDatabaseId: !empty(sourceDatabaseResourceId) ? sourceDatabaseResourceId : null sourceDatabaseDeletionDate: !empty(sourceDatabaseDeletionDate) ? sourceDatabaseDeletionDate : null - recoveryServicesRecoveryPointId: !empty(recoveryServicesRecoveryPointResourceId) ? recoveryServicesRecoveryPointResourceId : null + recoveryServicesRecoveryPointId: !empty(recoveryServicesRecoveryPointResourceId) + ? recoveryServicesRecoveryPointResourceId + : null restorePointInTime: !empty(restorePointInTime) ? restorePointInTime : null } sku: skuVar } -resource database_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource database_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: database } - scope: database -}] +] module database_backupShortTermRetentionPolicy 'backup-short-term-retention-policy/main.bicep' = { name: '${uniqueString(deployment().name, location)}-${name}-shBakRetPol' params: { serverName: serverName databaseName: database.name - diffBackupIntervalInHours: contains(backupShortTermRetentionPolicy, 'diffBackupIntervalInHours') ? backupShortTermRetentionPolicy.diffBackupIntervalInHours : 24 - retentionDays: contains(backupShortTermRetentionPolicy, 'retentionDays') ? backupShortTermRetentionPolicy.retentionDays : 7 + diffBackupIntervalInHours: contains(backupShortTermRetentionPolicy, 'diffBackupIntervalInHours') + ? backupShortTermRetentionPolicy.diffBackupIntervalInHours + : 24 + retentionDays: contains(backupShortTermRetentionPolicy, 'retentionDays') + ? backupShortTermRetentionPolicy.retentionDays + : 7 } } @@ -204,9 +225,15 @@ module database_backupLongTermRetentionPolicy 'backup-long-term-retention-policy params: { serverName: serverName databaseName: database.name - weeklyRetention: contains(backupLongTermRetentionPolicy, 'weeklyRetention') ? backupLongTermRetentionPolicy.weeklyRetention : '' - monthlyRetention: contains(backupLongTermRetentionPolicy, 'monthlyRetention') ? backupLongTermRetentionPolicy.monthlyRetention : '' - yearlyRetention: contains(backupLongTermRetentionPolicy, 'yearlyRetention') ? backupLongTermRetentionPolicy.yearlyRetention : '' + weeklyRetention: contains(backupLongTermRetentionPolicy, 'weeklyRetention') + ? backupLongTermRetentionPolicy.weeklyRetention + : '' + monthlyRetention: contains(backupLongTermRetentionPolicy, 'monthlyRetention') + ? backupLongTermRetentionPolicy.monthlyRetention + : '' + yearlyRetention: contains(backupLongTermRetentionPolicy, 'yearlyRetention') + ? backupLongTermRetentionPolicy.yearlyRetention + : '' weekOfYear: contains(backupLongTermRetentionPolicy, 'weekOfYear') ? backupLongTermRetentionPolicy.weekOfYear : 1 } } diff --git a/avm/res/sql/server/database/main.json b/avm/res/sql/server/database/main.json index e1a6b24ba4..b275733ac7 100644 --- a/avm/res/sql/server/database/main.json +++ b/avm/res/sql/server/database/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "745610238423132217" + "version": "0.26.54.24096", + "templateHash": "17545579739827867089" }, "name": "SQL Server Database", "description": "This module deploys an Azure SQL Server Database.", @@ -483,8 +483,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16471212899981632790" + "version": "0.26.54.24096", + "templateHash": "11085405057722780022" }, "name": "Azure SQL Server Database Short Term Backup Retention Policies", "description": "This module deploys an Azure SQL Server Database Short-Term Backup Retention Policy.", @@ -585,8 +585,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17376471861428793697" + "version": "0.26.54.24096", + "templateHash": "13590495271621282724" }, "name": "SQL Server Database Long Term Backup Retention Policies", "description": "This module deploys an Azure SQL Server Database Long-Term Backup Retention Policy.", diff --git a/avm/res/sql/server/elastic-pool/main.json b/avm/res/sql/server/elastic-pool/main.json index 04f10a84af..cc1804c480 100644 --- a/avm/res/sql/server/elastic-pool/main.json +++ b/avm/res/sql/server/elastic-pool/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3404184459089621320" + "version": "0.26.54.24096", + "templateHash": "16839451417800355426" }, "name": "SQL Server Elastic Pool", "description": "This module deploys an Azure SQL Server Elastic Pool.", diff --git a/avm/res/sql/server/encryption-protector/main.json b/avm/res/sql/server/encryption-protector/main.json index 2c6ab81141..c14369f9cc 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.25.53.49325", - "templateHash": "16485430925993626206" + "version": "0.26.54.24096", + "templateHash": "15754842645553898915" }, "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 211a03cd92..4f9b66749f 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.25.53.49325", - "templateHash": "6782455844016435325" + "version": "0.26.54.24096", + "templateHash": "11554996903169567204" }, "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.bicep b/avm/res/sql/server/key/main.bicep index 402a634b33..46ccaacaf4 100644 --- a/avm/res/sql/server/key/main.bicep +++ b/avm/res/sql/server/key/main.bicep @@ -22,7 +22,9 @@ var splittedKeyUri = split(uri, '/') // if serverManaged, use serverManaged, if uri provided use concated uri value // MUST match the pattern '__' -var serverKeyName = empty(uri) ? 'ServiceManaged' : '${split(splittedKeyUri[2], '.')[0]}_${splittedKeyUri[4]}_${splittedKeyUri[5]}' +var serverKeyName = empty(uri) + ? 'ServiceManaged' + : '${split(splittedKeyUri[2], '.')[0]}_${splittedKeyUri[4]}_${splittedKeyUri[5]}' resource server 'Microsoft.Sql/servers@2022-05-01-preview' existing = { name: serverName diff --git a/avm/res/sql/server/key/main.json b/avm/res/sql/server/key/main.json index f248bb2978..9d55f7c760 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.25.53.49325", - "templateHash": "8993850940520323522" + "version": "0.26.54.24096", + "templateHash": "5370214401001222813" }, "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 26f63c5646..b9243fc751 100644 --- a/avm/res/sql/server/main.bicep +++ b/avm/res/sql/server/main.bicep @@ -81,12 +81,20 @@ param publicNetworkAccess string = '' ]) param restrictOutboundNetworkAccess string = '' -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 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 @description('Optional. The encryption protection configuration.') param encryptionProtectorObj object = {} @@ -98,34 +106,62 @@ 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') - 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') - 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'SQL DB Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9b7fa17d-e63e-47b0-bb0a-15c516ac86ec') - 'SQL Managed Instance Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d') - 'SQL Security Manager': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3') - 'SQL Server Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437') - 'SqlDb Migration Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '189207d4-bb67-4208-a635-b06afe8b2c57') - 'SqlMI Migration Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d335eef-eee1-47fe-a9e0-53214eba8872') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Reservation Purchaser': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f7b75c60-3036-4b75-91c3-6b41c27c1689' + ) + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' + ) + 'SQL DB Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '9b7fa17d-e63e-47b0-bb0a-15c516ac86ec' + ) + 'SQL Managed Instance Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d' + ) + 'SQL Security Manager': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '056cd41c-7e88-42e1-933e-88ba6a50c9c3' + ) + 'SQL Server Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437' + ) + 'SqlDb Migration Role': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '189207d4-bb67-4208-a635-b06afe8b2c57' + ) + 'SqlMI Migration Role': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '1d335eef-eee1-47fe-a9e0-53214eba8872' + ) + 'User Access Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.sql-server.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.sql-server.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource server 'Microsoft.Sql/servers@2022-05-01-preview' = { location: location @@ -135,221 +171,297 @@ resource server 'Microsoft.Sql/servers@2022-05-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: !empty(administrators) + ? { + administratorType: 'ActiveDirectory' + azureADOnlyAuthentication: administrators.azureADOnlyAuthentication + login: administrators.login + principalType: administrators.principalType + sid: administrators.sid + tenantId: administrators.?tenantId ?? tenant().tenantId + } + : null version: '12.0' minimalTlsVersion: minimalTlsVersion primaryUserAssignedIdentityId: !empty(primaryUserAssignedIdentityId) ? primaryUserAssignedIdentityId : null - publicNetworkAccess: !empty(publicNetworkAccess) ? any(publicNetworkAccess) : (!empty(privateEndpoints) && empty(firewallRules) && empty(virtualNetworkRules) ? 'Disabled' : null) + publicNetworkAccess: !empty(publicNetworkAccess) + ? any(publicNetworkAccess) + : (!empty(privateEndpoints) && empty(firewallRules) && empty(virtualNetworkRules) ? 'Disabled' : null) restrictOutboundNetworkAccess: !empty(restrictOutboundNetworkAccess) ? restrictOutboundNetworkAccess : null } } -resource server_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.' +resource server_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: server } - scope: server -} -resource server_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(server.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource server_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(server.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: server } - scope: server -}] - -module server_databases 'database/main.bicep' = [for (database, index) in databases: { - name: '${uniqueString(deployment().name, location)}-Sql-DB-${index}' - params: { - name: database.name - serverName: server.name - skuTier: contains(database, 'skuTier') ? database.skuTier : 'GeneralPurpose' - skuName: contains(database, 'skuName') ? database.skuName : 'GP_Gen5_2' - skuCapacity: database.?skuCapacity - skuFamily: contains(database, 'skuFamily') ? database.skuFamily : '' - skuSize: contains(database, 'skuSize') ? database.skuSize : '' - collation: contains(database, 'collation') ? database.collation : 'SQL_Latin1_General_CP1_CI_AS' - maxSizeBytes: contains(database, 'maxSizeBytes') ? database.maxSizeBytes : 34359738368 - autoPauseDelay: contains(database, 'autoPauseDelay') ? database.autoPauseDelay : 0 - diagnosticSettings: database.?diagnosticSettings - isLedgerOn: contains(database, 'isLedgerOn') ? database.isLedgerOn : false - location: location - licenseType: contains(database, 'licenseType') ? database.licenseType : '' - maintenanceConfigurationId: contains(database, 'maintenanceConfigurationId') ? database.maintenanceConfigurationId : '' - minCapacity: contains(database, 'minCapacity') ? database.minCapacity : '' - highAvailabilityReplicaCount: contains(database, 'highAvailabilityReplicaCount') ? database.highAvailabilityReplicaCount : 0 - readScale: contains(database, 'readScale') ? database.readScale : 'Disabled' - requestedBackupStorageRedundancy: contains(database, 'requestedBackupStorageRedundancy') ? database.requestedBackupStorageRedundancy : '' - sampleName: contains(database, 'sampleName') ? database.sampleName : '' - tags: database.?tags ?? tags - zoneRedundant: contains(database, 'zoneRedundant') ? database.zoneRedundant : false - elasticPoolId: contains(database, 'elasticPoolId') ? database.elasticPoolId : '' - backupShortTermRetentionPolicy: contains(database, 'backupShortTermRetentionPolicy') ? database.backupShortTermRetentionPolicy : {} - backupLongTermRetentionPolicy: contains(database, 'backupLongTermRetentionPolicy') ? database.backupLongTermRetentionPolicy : {} - createMode: contains(database, 'createMode') ? database.createMode : 'Default' - sourceDatabaseResourceId: contains(database, 'sourceDatabaseResourceId') ? database.sourceDatabaseResourceId : '' - sourceDatabaseDeletionDate: contains(database, 'sourceDatabaseDeletionDate') ? database.sourceDatabaseDeletionDate : '' - recoveryServicesRecoveryPointResourceId: contains(database, 'recoveryServicesRecoveryPointResourceId') ? database.recoveryServicesRecoveryPointResourceId : '' - restorePointInTime: contains(database, 'restorePointInTime') ? database.restorePointInTime : '' +] + +module server_databases 'database/main.bicep' = [ + for (database, index) in databases: { + name: '${uniqueString(deployment().name, location)}-Sql-DB-${index}' + params: { + name: database.name + serverName: server.name + skuTier: contains(database, 'skuTier') ? database.skuTier : 'GeneralPurpose' + skuName: contains(database, 'skuName') ? database.skuName : 'GP_Gen5_2' + skuCapacity: database.?skuCapacity + skuFamily: contains(database, 'skuFamily') ? database.skuFamily : '' + skuSize: contains(database, 'skuSize') ? database.skuSize : '' + collation: contains(database, 'collation') ? database.collation : 'SQL_Latin1_General_CP1_CI_AS' + maxSizeBytes: contains(database, 'maxSizeBytes') ? database.maxSizeBytes : 34359738368 + autoPauseDelay: contains(database, 'autoPauseDelay') ? database.autoPauseDelay : 0 + diagnosticSettings: database.?diagnosticSettings + isLedgerOn: contains(database, 'isLedgerOn') ? database.isLedgerOn : false + location: location + licenseType: contains(database, 'licenseType') ? database.licenseType : '' + maintenanceConfigurationId: contains(database, 'maintenanceConfigurationId') + ? database.maintenanceConfigurationId + : '' + minCapacity: contains(database, 'minCapacity') ? database.minCapacity : '' + highAvailabilityReplicaCount: contains(database, 'highAvailabilityReplicaCount') + ? database.highAvailabilityReplicaCount + : 0 + readScale: contains(database, 'readScale') ? database.readScale : 'Disabled' + requestedBackupStorageRedundancy: contains(database, 'requestedBackupStorageRedundancy') + ? database.requestedBackupStorageRedundancy + : '' + sampleName: contains(database, 'sampleName') ? database.sampleName : '' + tags: database.?tags ?? tags + zoneRedundant: contains(database, 'zoneRedundant') ? database.zoneRedundant : false + elasticPoolId: contains(database, 'elasticPoolId') ? database.elasticPoolId : '' + backupShortTermRetentionPolicy: contains(database, 'backupShortTermRetentionPolicy') + ? database.backupShortTermRetentionPolicy + : {} + backupLongTermRetentionPolicy: contains(database, 'backupLongTermRetentionPolicy') + ? database.backupLongTermRetentionPolicy + : {} + createMode: contains(database, 'createMode') ? database.createMode : 'Default' + sourceDatabaseResourceId: contains(database, 'sourceDatabaseResourceId') ? database.sourceDatabaseResourceId : '' + sourceDatabaseDeletionDate: contains(database, 'sourceDatabaseDeletionDate') + ? database.sourceDatabaseDeletionDate + : '' + recoveryServicesRecoveryPointResourceId: contains(database, 'recoveryServicesRecoveryPointResourceId') + ? database.recoveryServicesRecoveryPointResourceId + : '' + restorePointInTime: contains(database, 'restorePointInTime') ? database.restorePointInTime : '' + } + dependsOn: [ + server_elasticPools // Enables us to add databases to existing elastic pools + ] } - dependsOn: [ - server_elasticPools // Enables us to add databases to existing elastic pools - ] -}] - -module server_elasticPools 'elastic-pool/main.bicep' = [for (elasticPool, index) in elasticPools: { - name: '${uniqueString(deployment().name, location)}-SQLServer-ElasticPool-${index}' - params: { - name: elasticPool.name - serverName: server.name - databaseMaxCapacity: contains(elasticPool, 'databaseMaxCapacity') ? elasticPool.databaseMaxCapacity : 2 - databaseMinCapacity: contains(elasticPool, 'databaseMinCapacity') ? elasticPool.databaseMinCapacity : 0 - highAvailabilityReplicaCount: elasticPool.?highAvailabilityReplicaCount - licenseType: contains(elasticPool, 'licenseType') ? elasticPool.licenseType : 'LicenseIncluded' - maintenanceConfigurationId: contains(elasticPool, 'maintenanceConfigurationId') ? elasticPool.maintenanceConfigurationId : '' - maxSizeBytes: contains(elasticPool, 'maxSizeBytes') ? elasticPool.maxSizeBytes : 34359738368 - minCapacity: elasticPool.?minCapacity - skuCapacity: contains(elasticPool, 'skuCapacity') ? elasticPool.skuCapacity : 2 - skuName: contains(elasticPool, 'skuName') ? elasticPool.skuName : 'GP_Gen5' - skuTier: contains(elasticPool, 'skuTier') ? elasticPool.skuTier : 'GeneralPurpose' - zoneRedundant: contains(elasticPool, 'zoneRedundant') ? elasticPool.zoneRedundant : false - location: location - tags: elasticPool.?tags ?? tags +] + +module server_elasticPools 'elastic-pool/main.bicep' = [ + for (elasticPool, index) in elasticPools: { + name: '${uniqueString(deployment().name, location)}-SQLServer-ElasticPool-${index}' + params: { + name: elasticPool.name + serverName: server.name + databaseMaxCapacity: contains(elasticPool, 'databaseMaxCapacity') ? elasticPool.databaseMaxCapacity : 2 + databaseMinCapacity: contains(elasticPool, 'databaseMinCapacity') ? elasticPool.databaseMinCapacity : 0 + highAvailabilityReplicaCount: elasticPool.?highAvailabilityReplicaCount + licenseType: contains(elasticPool, 'licenseType') ? elasticPool.licenseType : 'LicenseIncluded' + maintenanceConfigurationId: contains(elasticPool, 'maintenanceConfigurationId') + ? elasticPool.maintenanceConfigurationId + : '' + maxSizeBytes: contains(elasticPool, 'maxSizeBytes') ? elasticPool.maxSizeBytes : 34359738368 + minCapacity: elasticPool.?minCapacity + skuCapacity: contains(elasticPool, 'skuCapacity') ? elasticPool.skuCapacity : 2 + skuName: contains(elasticPool, 'skuName') ? elasticPool.skuName : 'GP_Gen5' + skuTier: contains(elasticPool, 'skuTier') ? elasticPool.skuTier : 'GeneralPurpose' + zoneRedundant: contains(elasticPool, 'zoneRedundant') ? elasticPool.zoneRedundant : false + location: location + tags: elasticPool.?tags ?? tags + } } -}] - -module server_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-Server-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(server.id, '/'))}-${privateEndpoint.?service ?? 'sqlServer'}-${index}' - privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(server.id, '/'))}-${privateEndpoint.?service ?? 'sqlServer'}-${index}' - properties: { - privateLinkServiceId: server.id - groupIds: [ - privateEndpoint.?service ?? 'sqlServer' +] + +module server_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-Server-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(server.id, '/'))}-${privateEndpoint.?service ?? 'sqlServer'}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(server.id, '/'))}-${privateEndpoint.?service ?? 'sqlServer'}-${index}' + properties: { + privateLinkServiceId: server.id + groupIds: [ + privateEndpoint.?service ?? 'sqlServer' + ] + } + } ] - } - } - ] : null - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(server.id, '/'))}-${privateEndpoint.?service ?? 'sqlServer'}-${index}' - properties: { - privateLinkServiceId: server.id - groupIds: [ - privateEndpoint.?service ?? 'sqlServer' + : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(server.id, '/'))}-${privateEndpoint.?service ?? 'sqlServer'}-${index}' + properties: { + privateLinkServiceId: server.id + groupIds: [ + privateEndpoint.?service ?? 'sqlServer' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] - -module server_firewallRules 'firewall-rule/main.bicep' = [for (firewallRule, index) in firewallRules: { - name: '${uniqueString(deployment().name, location)}-Sql-FirewallRules-${index}' - params: { - name: firewallRule.name - serverName: server.name - endIpAddress: contains(firewallRule, 'endIpAddress') ? firewallRule.endIpAddress : '0.0.0.0' - startIpAddress: contains(firewallRule, 'startIpAddress') ? firewallRule.startIpAddress : '0.0.0.0' +] + +module server_firewallRules 'firewall-rule/main.bicep' = [ + for (firewallRule, index) in firewallRules: { + name: '${uniqueString(deployment().name, location)}-Sql-FirewallRules-${index}' + params: { + name: firewallRule.name + serverName: server.name + endIpAddress: contains(firewallRule, 'endIpAddress') ? firewallRule.endIpAddress : '0.0.0.0' + startIpAddress: contains(firewallRule, 'startIpAddress') ? firewallRule.startIpAddress : '0.0.0.0' + } } -}] - -module server_virtualNetworkRules 'virtual-network-rule/main.bicep' = [for (virtualNetworkRule, index) in virtualNetworkRules: { - name: '${uniqueString(deployment().name, location)}-Sql-VirtualNetworkRules-${index}' - params: { - name: virtualNetworkRule.name - serverName: server.name - ignoreMissingVnetServiceEndpoint: contains(virtualNetworkRule, 'ignoreMissingVnetServiceEndpoint') ? virtualNetworkRule.ignoreMissingVnetServiceEndpoint : false - virtualNetworkSubnetId: virtualNetworkRule.virtualNetworkSubnetId +] + +module server_virtualNetworkRules 'virtual-network-rule/main.bicep' = [ + for (virtualNetworkRule, index) in virtualNetworkRules: { + name: '${uniqueString(deployment().name, location)}-Sql-VirtualNetworkRules-${index}' + params: { + name: virtualNetworkRule.name + serverName: server.name + ignoreMissingVnetServiceEndpoint: contains(virtualNetworkRule, 'ignoreMissingVnetServiceEndpoint') + ? virtualNetworkRule.ignoreMissingVnetServiceEndpoint + : false + virtualNetworkSubnetId: virtualNetworkRule.virtualNetworkSubnetId + } } -}] - -module server_securityAlertPolicies 'security-alert-policy/main.bicep' = [for (securityAlertPolicy, index) in securityAlertPolicies: { - name: '${uniqueString(deployment().name, location)}-Sql-SecAlertPolicy-${index}' - params: { - name: securityAlertPolicy.name - serverName: server.name - disabledAlerts: contains(securityAlertPolicy, 'disabledAlerts') ? securityAlertPolicy.disabledAlerts : [] - emailAccountAdmins: contains(securityAlertPolicy, 'emailAccountAdmins') ? securityAlertPolicy.emailAccountAdmins : false - emailAddresses: contains(securityAlertPolicy, 'emailAddresses') ? securityAlertPolicy.emailAddresses : [] - retentionDays: contains(securityAlertPolicy, 'retentionDays') ? securityAlertPolicy.retentionDays : 0 - state: contains(securityAlertPolicy, 'state') ? securityAlertPolicy.state : 'Disabled' - storageAccountAccessKey: contains(securityAlertPolicy, 'storageAccountAccessKey') ? securityAlertPolicy.storageAccountAccessKey : '' - storageEndpoint: contains(securityAlertPolicy, 'storageEndpoint') ? securityAlertPolicy.storageEndpoint : '' +] + +module server_securityAlertPolicies 'security-alert-policy/main.bicep' = [ + for (securityAlertPolicy, index) in securityAlertPolicies: { + name: '${uniqueString(deployment().name, location)}-Sql-SecAlertPolicy-${index}' + params: { + name: securityAlertPolicy.name + serverName: server.name + disabledAlerts: contains(securityAlertPolicy, 'disabledAlerts') ? securityAlertPolicy.disabledAlerts : [] + emailAccountAdmins: contains(securityAlertPolicy, 'emailAccountAdmins') + ? securityAlertPolicy.emailAccountAdmins + : false + emailAddresses: contains(securityAlertPolicy, 'emailAddresses') ? securityAlertPolicy.emailAddresses : [] + retentionDays: contains(securityAlertPolicy, 'retentionDays') ? securityAlertPolicy.retentionDays : 0 + state: contains(securityAlertPolicy, 'state') ? securityAlertPolicy.state : 'Disabled' + storageAccountAccessKey: contains(securityAlertPolicy, 'storageAccountAccessKey') + ? securityAlertPolicy.storageAccountAccessKey + : '' + storageEndpoint: contains(securityAlertPolicy, 'storageEndpoint') ? securityAlertPolicy.storageEndpoint : '' + } } -}] - -module server_vulnerabilityAssessment 'vulnerability-assessment/main.bicep' = if (!empty(vulnerabilityAssessmentsObj)) { - name: '${uniqueString(deployment().name, location)}-Sql-VulnAssessm' - params: { - serverName: server.name - name: vulnerabilityAssessmentsObj.name - recurringScansEmails: contains(vulnerabilityAssessmentsObj, 'recurringScansEmails') ? vulnerabilityAssessmentsObj.recurringScansEmails : [] - recurringScansEmailSubscriptionAdmins: contains(vulnerabilityAssessmentsObj, 'recurringScansEmailSubscriptionAdmins') ? vulnerabilityAssessmentsObj.recurringScansEmailSubscriptionAdmins : false - recurringScansIsEnabled: contains(vulnerabilityAssessmentsObj, 'recurringScansIsEnabled') ? vulnerabilityAssessmentsObj.recurringScansIsEnabled : false - storageAccountResourceId: vulnerabilityAssessmentsObj.storageAccountResourceId - useStorageAccountAccessKey: contains(vulnerabilityAssessmentsObj, 'useStorageAccountAccessKey') ? vulnerabilityAssessmentsObj.useStorageAccountAccessKey : false - createStorageRoleAssignment: contains(vulnerabilityAssessmentsObj, 'createStorageRoleAssignment') ? vulnerabilityAssessmentsObj.createStorageRoleAssignment : true +] + +module server_vulnerabilityAssessment 'vulnerability-assessment/main.bicep' = + if (!empty(vulnerabilityAssessmentsObj)) { + name: '${uniqueString(deployment().name, location)}-Sql-VulnAssessm' + params: { + serverName: server.name + name: vulnerabilityAssessmentsObj.name + recurringScansEmails: contains(vulnerabilityAssessmentsObj, 'recurringScansEmails') + ? vulnerabilityAssessmentsObj.recurringScansEmails + : [] + recurringScansEmailSubscriptionAdmins: contains( + vulnerabilityAssessmentsObj, + 'recurringScansEmailSubscriptionAdmins' + ) + ? vulnerabilityAssessmentsObj.recurringScansEmailSubscriptionAdmins + : false + recurringScansIsEnabled: contains(vulnerabilityAssessmentsObj, 'recurringScansIsEnabled') + ? vulnerabilityAssessmentsObj.recurringScansIsEnabled + : false + storageAccountResourceId: vulnerabilityAssessmentsObj.storageAccountResourceId + useStorageAccountAccessKey: contains(vulnerabilityAssessmentsObj, 'useStorageAccountAccessKey') + ? vulnerabilityAssessmentsObj.useStorageAccountAccessKey + : false + createStorageRoleAssignment: contains(vulnerabilityAssessmentsObj, 'createStorageRoleAssignment') + ? vulnerabilityAssessmentsObj.createStorageRoleAssignment + : true + } + dependsOn: [ + server_securityAlertPolicies + ] } - dependsOn: [ - server_securityAlertPolicies - ] -} -module server_keys 'key/main.bicep' = [for (key, index) in keys: { - name: '${uniqueString(deployment().name, location)}-Sql-Key-${index}' - params: { - name: key.?name - serverName: server.name - serverKeyType: contains(key, 'serverKeyType') ? key.serverKeyType : 'ServiceManaged' - uri: contains(key, 'uri') ? key.uri : '' +module server_keys 'key/main.bicep' = [ + for (key, index) in keys: { + name: '${uniqueString(deployment().name, location)}-Sql-Key-${index}' + params: { + name: key.?name + serverName: server.name + serverKeyType: contains(key, 'serverKeyType') ? key.serverKeyType : 'ServiceManaged' + uri: contains(key, 'uri') ? key.uri : '' + } } -}] - -module server_encryptionProtector 'encryption-protector/main.bicep' = if (!empty(encryptionProtectorObj)) { - name: '${uniqueString(deployment().name, location)}-Sql-EncryProtector' - params: { - sqlServerName: server.name - serverKeyName: encryptionProtectorObj.serverKeyName - serverKeyType: contains(encryptionProtectorObj, 'serverKeyType') ? encryptionProtectorObj.serverKeyType : 'ServiceManaged' - autoRotationEnabled: contains(encryptionProtectorObj, 'autoRotationEnabled') ? encryptionProtectorObj.autoRotationEnabled : true +] + +module server_encryptionProtector 'encryption-protector/main.bicep' = + if (!empty(encryptionProtectorObj)) { + name: '${uniqueString(deployment().name, location)}-Sql-EncryProtector' + params: { + sqlServerName: server.name + serverKeyName: encryptionProtectorObj.serverKeyName + serverKeyType: contains(encryptionProtectorObj, 'serverKeyType') + ? encryptionProtectorObj.serverKeyType + : 'ServiceManaged' + autoRotationEnabled: contains(encryptionProtectorObj, 'autoRotationEnabled') + ? encryptionProtectorObj.autoRotationEnabled + : true + } + dependsOn: [ + server_keys + ] } - dependsOn: [ - server_keys - ] -} @description('The name of the deployed SQL server.') output name string = server.name diff --git a/avm/res/sql/server/main.json b/avm/res/sql/server/main.json index 5373bb5ebe..1323c000f0 100644 --- a/avm/res/sql/server/main.json +++ b/avm/res/sql/server/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "6171976598584344196" + "version": "0.26.54.24096", + "templateHash": "1498326047864414566" }, "name": "Azure SQL Servers", "description": "This module deploys an Azure SQL Server.", @@ -641,8 +641,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "745610238423132217" + "version": "0.26.54.24096", + "templateHash": "17545579739827867089" }, "name": "SQL Server Database", "description": "This module deploys an Azure SQL Server Database.", @@ -1119,8 +1119,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16471212899981632790" + "version": "0.26.54.24096", + "templateHash": "11085405057722780022" }, "name": "Azure SQL Server Database Short Term Backup Retention Policies", "description": "This module deploys an Azure SQL Server Database Short-Term Backup Retention Policy.", @@ -1221,8 +1221,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17376471861428793697" + "version": "0.26.54.24096", + "templateHash": "13590495271621282724" }, "name": "SQL Server Database Long Term Backup Retention Policies", "description": "This module deploys an Azure SQL Server Database Long-Term Backup Retention Policy.", @@ -1399,8 +1399,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3404184459089621320" + "version": "0.26.54.24096", + "templateHash": "16839451417800355426" }, "name": "SQL Server Elastic Pool", "description": "This module deploys an Azure SQL Server Elastic Pool.", @@ -2276,8 +2276,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "6782455844016435325" + "version": "0.26.54.24096", + "templateHash": "11554996903169567204" }, "name": "Azure SQL Server Firewall Rule", "description": "This module deploys an Azure SQL Server Firewall Rule.", @@ -2382,8 +2382,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16350137843713909320" + "version": "0.26.54.24096", + "templateHash": "16468636891412424894" }, "name": "Azure SQL Server Virtual Network Rules", "description": "This module deploys an Azure SQL Server Virtual Network Rule.", @@ -2490,8 +2490,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "12316453108388638438" + "version": "0.26.54.24096", + "templateHash": "4552154846289317547" }, "name": "Azure SQL Server Security Alert Policies", "description": "This module deploys an Azure SQL Server Security Alert Policy.", @@ -2641,8 +2641,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11132162611657015619" + "version": "0.26.54.24096", + "templateHash": "5720200901996028671" }, "name": "Azure SQL Server Vulnerability Assessments", "description": "This module deploys an Azure SQL Server Vulnerability Assessment.", @@ -2744,8 +2744,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "7342984307461208675" + "version": "0.26.54.24096", + "templateHash": "13552747005956537738" } }, "parameters": { @@ -2833,8 +2833,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "8993850940520323522" + "version": "0.26.54.24096", + "templateHash": "5370214401001222813" }, "name": "Azure SQL Server Keys", "description": "This module deploys an Azure SQL Server Key.", @@ -2952,8 +2952,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16485430925993626206" + "version": "0.26.54.24096", + "templateHash": "15754842645553898915" }, "name": "Azure SQL Server Encryption Protector", "description": "This module deploys an Azure SQL Server Encryption Protector.", diff --git a/avm/res/sql/server/security-alert-policy/main.json b/avm/res/sql/server/security-alert-policy/main.json index c0350da7f4..0041bd7154 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.25.53.49325", - "templateHash": "12316453108388638438" + "version": "0.26.54.24096", + "templateHash": "4552154846289317547" }, "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/defaults/main.test.bicep b/avm/res/sql/server/tests/e2e/defaults/main.test.bicep index b2b9f5c769..a6bb47978f 100644 --- a/avm/res/sql/server/tests/e2e/defaults/main.test.bicep +++ b/avm/res/sql/server/tests/e2e/defaults/main.test.bicep @@ -42,13 +42,15 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 +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 + } } -}] +] diff --git a/avm/res/sql/server/tests/e2e/max/dependencies.bicep b/avm/res/sql/server/tests/e2e/max/dependencies.bicep index 5f68856202..3698ac0ac5 100644 --- a/avm/res/sql/server/tests/e2e/max/dependencies.bicep +++ b/avm/res/sql/server/tests/e2e/max/dependencies.bicep @@ -26,12 +26,15 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { addressPrefix ] } - subnets: map(range(0, 2), i => { + subnets: map( + range(0, 2), + i => { name: 'subnet-${i}' properties: { addressPrefix: cidrSubnet(addressPrefix, 24, i) } - }) + } + ) } } @@ -81,7 +84,10 @@ resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { scope: keyVault::key properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6') // Key Vault Crypto Service Encryption User + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'e147488a-f6f5-4113-8e2d-b22465e65bf6' + ) // Key Vault Crypto Service Encryption User principalType: 'ServicePrincipal' } } 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 01ea249410..92abcc0971 100644 --- a/avm/res/sql/server/tests/e2e/max/main.test.bicep +++ b/avm/res/sql/server/tests/e2e/max/main.test.bicep @@ -89,7 +89,10 @@ module testDeployment '../../../main.bicep' = { principalType: 'ServicePrincipal' } { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) principalId: nestedDependencies.outputs.managedIdentityPrincipalId principalType: 'ServicePrincipal' } 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 5f68856202..3698ac0ac5 100644 --- a/avm/res/sql/server/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/sql/server/tests/e2e/waf-aligned/dependencies.bicep @@ -26,12 +26,15 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { addressPrefix ] } - subnets: map(range(0, 2), i => { + subnets: map( + range(0, 2), + i => { name: 'subnet-${i}' properties: { addressPrefix: cidrSubnet(addressPrefix, 24, i) } - }) + } + ) } } @@ -81,7 +84,10 @@ resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { scope: keyVault::key properties: { principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6') // Key Vault Crypto Service Encryption User + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'e147488a-f6f5-4113-8e2d-b22465e65bf6' + ) // Key Vault Crypto Service Encryption User principalType: 'ServicePrincipal' } } diff --git a/avm/res/sql/server/virtual-network-rule/main.json b/avm/res/sql/server/virtual-network-rule/main.json index 1520ebf1a8..6ab064ab7c 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.25.53.49325", - "templateHash": "16350137843713909320" + "version": "0.26.54.24096", + "templateHash": "16468636891412424894" }, "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.bicep b/avm/res/sql/server/vulnerability-assessment/main.bicep index 519123f228..5156556584 100644 --- a/avm/res/sql/server/vulnerability-assessment/main.bicep +++ b/avm/res/sql/server/vulnerability-assessment/main.bicep @@ -31,21 +31,24 @@ resource server 'Microsoft.Sql/servers@2022-05-01-preview' existing = { } // Assign SQL Server MSI access to storage account -module storageAccount_sbdc_rbac 'modules/nested_storageRoleAssignment.bicep' = if (!useStorageAccountAccessKey && createStorageRoleAssignment) { - name: '${server.name}-sbdc-rbac' - scope: resourceGroup(split(storageAccountResourceId, '/')[2], split(storageAccountResourceId, '/')[4]) - params: { - storageAccountName: last(split(storageAccountResourceId, '/')) - managedInstanceIdentityPrincipalId: server.identity.principalId +module storageAccount_sbdc_rbac 'modules/nested_storageRoleAssignment.bicep' = + if (!useStorageAccountAccessKey && createStorageRoleAssignment) { + name: '${server.name}-sbdc-rbac' + scope: resourceGroup(split(storageAccountResourceId, '/')[2], split(storageAccountResourceId, '/')[4]) + params: { + storageAccountName: last(split(storageAccountResourceId, '/')) + managedInstanceIdentityPrincipalId: server.identity.principalId + } } -} resource vulnerabilityAssessment 'Microsoft.Sql/servers/vulnerabilityAssessments@2022-05-01-preview' = { name: name parent: server properties: { storageContainerPath: 'https://${last(split(storageAccountResourceId, '/'))}.blob.${environment().suffixes.storage}/vulnerability-assessment/' - storageAccountAccessKey: useStorageAccountAccessKey ? listKeys(storageAccountResourceId, '2019-06-01').keys[0].value : any(null) + storageAccountAccessKey: useStorageAccountAccessKey + ? listKeys(storageAccountResourceId, '2019-06-01').keys[0].value + : any(null) recurringScans: { isEnabled: recurringScansIsEnabled emailSubscriptionAdmins: recurringScansEmailSubscriptionAdmins diff --git a/avm/res/sql/server/vulnerability-assessment/main.json b/avm/res/sql/server/vulnerability-assessment/main.json index 8dfe8d48a8..1aad66da11 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.25.53.49325", - "templateHash": "11132162611657015619" + "version": "0.26.54.24096", + "templateHash": "5720200901996028671" }, "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.25.53.49325", - "templateHash": "7342984307461208675" + "version": "0.26.54.24096", + "templateHash": "13552747005956537738" } }, "parameters": { diff --git a/avm/res/storage/storage-account/blob-service/container/immutability-policy/main.json b/avm/res/storage/storage-account/blob-service/container/immutability-policy/main.json index ac3bd2c129..91a31edc0d 100644 --- a/avm/res/storage/storage-account/blob-service/container/immutability-policy/main.json +++ b/avm/res/storage/storage-account/blob-service/container/immutability-policy/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "10329548264889228160" + "version": "0.26.54.24096", + "templateHash": "2429139364933838439" }, "name": "Storage Account Blob Container Immutability Policies", "description": "This module deploys a Storage Account Blob Container Immutability Policy.", 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 3f3a51ac90..a41cc7b8ce 100644 --- a/avm/res/storage/storage-account/blob-service/container/main.json +++ b/avm/res/storage/storage-account/blob-service/container/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11351273351916968732" + "version": "0.26.54.24096", + "templateHash": "3297137219061666309" }, "name": "Storage Account Blob Containers", "description": "This module deploys a Storage Account Blob Container.", @@ -274,8 +274,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "10329548264889228160" + "version": "0.26.54.24096", + "templateHash": "2429139364933838439" }, "name": "Storage Account Blob Container Immutability Policies", "description": "This module deploys a Storage Account Blob Container Immutability Policy.", diff --git a/avm/res/storage/storage-account/blob-service/main.json b/avm/res/storage/storage-account/blob-service/main.json index 46429e3bb4..2ac6992281 100644 --- a/avm/res/storage/storage-account/blob-service/main.json +++ b/avm/res/storage/storage-account/blob-service/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4746835745355709536" + "version": "0.26.54.24096", + "templateHash": "12175020972967228537" }, "name": "Storage Account blob Services", "description": "This module deploys a Storage Account Blob Service.", @@ -403,8 +403,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11351273351916968732" + "version": "0.26.54.24096", + "templateHash": "3297137219061666309" }, "name": "Storage Account Blob Containers", "description": "This module deploys a Storage Account Blob Container.", @@ -672,8 +672,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "10329548264889228160" + "version": "0.26.54.24096", + "templateHash": "2429139364933838439" }, "name": "Storage Account Blob Container Immutability Policies", "description": "This module deploys a Storage Account Blob Container Immutability Policy.", diff --git a/avm/res/storage/storage-account/file-service/main.json b/avm/res/storage/storage-account/file-service/main.json index b2d1773a8a..38dcbcb7c7 100644 --- a/avm/res/storage/storage-account/file-service/main.json +++ b/avm/res/storage/storage-account/file-service/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "5288106279947156711" + "version": "0.26.54.24096", + "templateHash": "13860799899517512764" }, "name": "Storage Account File Share Services", "description": "This module deploys a Storage Account File Share Service.", @@ -286,8 +286,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2026482374148202879" + "version": "0.26.54.24096", + "templateHash": "18405917853511220559" }, "name": "Storage Account File Shares", "description": "This module deploys a Storage Account File Share.", @@ -486,8 +486,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "15595600813016932186" + "version": "0.26.54.24096", + "templateHash": "16221226236637657314" } }, "parameters": { 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 4d6e95dba4..813cd74fbd 100644 --- a/avm/res/storage/storage-account/file-service/share/main.json +++ b/avm/res/storage/storage-account/file-service/share/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "2026482374148202879" + "version": "0.26.54.24096", + "templateHash": "18405917853511220559" }, "name": "Storage Account File Shares", "description": "This module deploys a Storage Account File Share.", @@ -205,8 +205,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "15595600813016932186" + "version": "0.26.54.24096", + "templateHash": "16221226236637657314" } }, "parameters": { diff --git a/avm/res/storage/storage-account/local-user/main.json b/avm/res/storage/storage-account/local-user/main.json index 5044c80422..07d5ea2520 100644 --- a/avm/res/storage/storage-account/local-user/main.json +++ b/avm/res/storage/storage-account/local-user/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17117452291389534361" + "version": "0.26.54.24096", + "templateHash": "3388645117303533667" }, "name": "Storage Account Local Users", "description": "This module deploys a Storage Account Local User, which is used for SFTP authentication.", diff --git a/avm/res/storage/storage-account/main.bicep b/avm/res/storage/storage-account/main.bicep index f95b1f1f23..1b4437ab21 100644 --- a/avm/res/storage/storage-account/main.bicep +++ b/avm/res/storage/storage-account/main.bicep @@ -95,12 +95,14 @@ param customDomainUseSubDomainName bool = false param dnsEndpointType string = '' @description('Optional. Blob service and containers to deploy.') -param blobServices object = kind != 'FileStorage' ? { - containerDeleteRetentionPolicyEnabled: true - containerDeleteRetentionPolicyDays: 7 - deleteRetentionPolicyEnabled: true - deleteRetentionPolicyDays: 6 -} : {} +param blobServices object = kind != 'FileStorage' + ? { + containerDeleteRetentionPolicyEnabled: true + containerDeleteRetentionPolicyDays: 7 + deleteRetentionPolicyEnabled: true + deleteRetentionPolicyDays: 6 + } + : {} @description('Optional. File service and shares to deploy.') param fileServices object = {} @@ -177,69 +179,144 @@ param sasExpirationPeriod string = '' var supportsBlobService = kind == 'BlockBlobStorage' || kind == 'BlobStorage' || kind == 'StorageV2' || kind == 'Storage' var supportsFileService = kind == 'FileStorage' || kind == 'StorageV2' || kind == 'Storage' -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' : 'None') - userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null -} : null +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' : 'None') + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null + } + : 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') - 'Reader and Data Access': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349') - 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'Storage Account Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1') - 'Storage Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab') - 'Storage Account Key Operator Service Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12') - 'Storage Blob Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe') - 'Storage Blob Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b') - 'Storage Blob Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1') - 'Storage Blob Delegator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a') - 'Storage File Data SMB Share Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb') - 'Storage File Data SMB Share Elevated Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7') - 'Storage File Data SMB Share Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314') - 'Storage Queue Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88') - 'Storage Queue Data Message Processor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed') - 'Storage Queue Data Message Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a') - 'Storage Queue Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925') - 'Storage Table Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3') - 'Storage Table Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76199698-9eea-4c19-bc75-cec21354c6b6') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Reader and Data Access': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'c12c1c16-33a1-487b-954d-41c89c60f349' + ) + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' + ) + 'Storage Account Backup Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1' + ) + 'Storage Account Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '17d1049b-9a84-46fb-8f53-869881c3d3ab' + ) + 'Storage Account Key Operator Service Role': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '81a9662b-bebf-436f-a333-f67b29880f12' + ) + 'Storage Blob Data Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'ba92f5b4-2d11-453d-a403-e96b0029c9fe' + ) + 'Storage Blob Data Owner': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b' + ) + 'Storage Blob Data Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1' + ) + 'Storage Blob Delegator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a' + ) + 'Storage File Data SMB Share Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb' + ) + 'Storage File Data SMB Share Elevated Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'a7264617-510b-434b-a828-9731dc254ea7' + ) + 'Storage File Data SMB Share Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'aba4ae5f-2193-4029-9191-0cb91df5e314' + ) + 'Storage Queue Data Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '974c5e8b-45b9-4653-ba55-5f855dd0fb88' + ) + 'Storage Queue Data Message Processor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '8a0f0c08-91a1-4084-bc3d-661d67233fed' + ) + 'Storage Queue Data Message Sender': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a' + ) + 'Storage Queue Data Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '19e7f393-937e-4f77-808e-94535e297925' + ) + 'Storage Table Data Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3' + ) + 'Storage Table Data Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '76199698-9eea-4c19-bc75-cec21354c6b6' + ) + 'User Access Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.storage-storageaccount.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.storage-storageaccount.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} -resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId)) { - name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) - scope: resourceGroup(split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4]) - - resource cMKKey 'keys@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { - name: customerManagedKey.?keyName ?? 'dummyKey' +resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = + if (!empty(customerManagedKey.?keyVaultResourceId)) { + name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) + scope: resourceGroup( + split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], + split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4] + ) + + resource cMKKey 'keys@2023-02-01' existing = + if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { + name: customerManagedKey.?keyName ?? 'dummyKey' + } } -} -resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { - name: last(split(customerManagedKey.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) - scope: resourceGroup(split((customerManagedKey.?userAssignedIdentityResourceId ?? '//'), '/')[2], split((customerManagedKey.?userAssignedIdentityResourceId ?? '////'), '/')[4]) -} +resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = + if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { + name: last(split(customerManagedKey.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) + scope: resourceGroup( + split((customerManagedKey.?userAssignedIdentityResourceId ?? '//'), '/')[2], + split((customerManagedKey.?userAssignedIdentityResourceId ?? '////'), '/')[4] + ) + } resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' = { name: name @@ -261,15 +338,20 @@ resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' = { } dnsEndpointType: !empty(dnsEndpointType) ? dnsEndpointType : null isLocalUserEnabled: isLocalUserEnabled - encryption: union({ + encryption: union( + { keySource: !empty(customerManagedKey) ? 'Microsoft.Keyvault' : 'Microsoft.Storage' services: { - blob: supportsBlobService ? { - enabled: true - } : null - file: supportsFileService ? { - enabled: true - } : null + blob: supportsBlobService + ? { + enabled: true + } + : null + file: supportsFileService + ? { + enabled: true + } + : null table: { enabled: true } @@ -277,207 +359,255 @@ resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' = { enabled: true } } - keyvaultproperties: !empty(customerManagedKey) ? { - keyname: customerManagedKey!.keyName - keyvaulturi: cMKKeyVault.properties.vaultUri - keyversion: !empty(customerManagedKey.?keyVersion ?? '') ? customerManagedKey!.keyVersion : last(split(cMKKeyVault::cMKKey.properties.keyUriWithVersion, '/')) - } : null + keyvaultproperties: !empty(customerManagedKey) + ? { + keyname: customerManagedKey!.keyName + keyvaulturi: cMKKeyVault.properties.vaultUri + keyversion: !empty(customerManagedKey.?keyVersion ?? '') + ? customerManagedKey!.keyVersion + : last(split(cMKKeyVault::cMKKey.properties.keyUriWithVersion, '/')) + } + : null identity: { - userAssignedIdentity: !empty(customerManagedKey.?userAssignedIdentityResourceId) ? cMKUserAssignedIdentity.id : null + userAssignedIdentity: !empty(customerManagedKey.?userAssignedIdentityResourceId) + ? cMKUserAssignedIdentity.id + : null } - }, (requireInfrastructureEncryption ? { - requireInfrastructureEncryption: kind != 'Storage' ? requireInfrastructureEncryption : null - } : {})) + }, + (requireInfrastructureEncryption + ? { + requireInfrastructureEncryption: kind != 'Storage' ? requireInfrastructureEncryption : null + } + : {}) + ) accessTier: (kind != 'Storage' && kind != 'BlockBlobStorage') ? accessTier : null - sasPolicy: !empty(sasExpirationPeriod) ? { - expirationAction: 'Log' - sasExpirationPeriod: sasExpirationPeriod - } : null + sasPolicy: !empty(sasExpirationPeriod) + ? { + expirationAction: 'Log' + sasExpirationPeriod: sasExpirationPeriod + } + : null supportsHttpsTrafficOnly: supportsHttpsTrafficOnly isHnsEnabled: enableHierarchicalNamespace ? enableHierarchicalNamespace : null isSftpEnabled: enableSftp isNfsV3Enabled: enableNfsV3 ? enableNfsV3 : any('') largeFileSharesState: (skuName == 'Standard_LRS') || (skuName == 'Standard_ZRS') ? largeFileSharesState : null minimumTlsVersion: minimumTlsVersion - networkAcls: !empty(networkAcls) ? { - resourceAccessRules: networkAcls.?resourceAccessRules - bypass: networkAcls.?bypass - defaultAction: networkAcls.?defaultAction - virtualNetworkRules: networkAcls.?virtualNetworkRules - ipRules: networkAcls.?ipRules - } : null + networkAcls: !empty(networkAcls) + ? { + resourceAccessRules: networkAcls.?resourceAccessRules + bypass: networkAcls.?bypass + defaultAction: networkAcls.?defaultAction + virtualNetworkRules: networkAcls.?virtualNetworkRules + ipRules: networkAcls.?ipRules + } + : null allowBlobPublicAccess: allowBlobPublicAccess - publicNetworkAccess: !empty(publicNetworkAccess) ? any(publicNetworkAccess) : (!empty(privateEndpoints) && empty(networkAcls) ? 'Disabled' : null) - azureFilesIdentityBasedAuthentication: !empty(azureFilesIdentityBasedAuthentication) ? azureFilesIdentityBasedAuthentication : null + publicNetworkAccess: !empty(publicNetworkAccess) + ? any(publicNetworkAccess) + : (!empty(privateEndpoints) && empty(networkAcls) ? 'Disabled' : null) + azureFilesIdentityBasedAuthentication: !empty(azureFilesIdentityBasedAuthentication) + ? azureFilesIdentityBasedAuthentication + : null } } -resource storageAccount_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource storageAccount_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: storageAccount } - scope: storageAccount -}] +] -resource storageAccount_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.' +resource storageAccount_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: storageAccount } - scope: storageAccount -} -resource storageAccount_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(storageAccount.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource storageAccount_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(storageAccount.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: storageAccount } - scope: storageAccount -}] - -module storageAccount_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-StorageAccount-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(storageAccount.id, '/'))}-${privateEndpoint.service}-${index}' - privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(storageAccount.id, '/'))}-${privateEndpoint.service}-${index}' - properties: { - privateLinkServiceId: storageAccount.id - groupIds: [ - privateEndpoint.service +] + +module storageAccount_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-StorageAccount-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(storageAccount.id, '/'))}-${privateEndpoint.service}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(storageAccount.id, '/'))}-${privateEndpoint.service}-${index}' + properties: { + privateLinkServiceId: storageAccount.id + groupIds: [ + privateEndpoint.service + ] + } + } ] - } - } - ] : null - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(storageAccount.id, '/'))}-${privateEndpoint.service}-${index}' - properties: { - privateLinkServiceId: storageAccount.id - groupIds: [ - privateEndpoint.service + : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(storageAccount.id, '/'))}-${privateEndpoint.service}-${index}' + properties: { + privateLinkServiceId: storageAccount.id + groupIds: [ + privateEndpoint.service + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] +] // Lifecycle Policy -module storageAccount_managementPolicies 'management-policy/main.bicep' = if (!empty(managementPolicyRules ?? [])) { - name: '${uniqueString(deployment().name, location)}-Storage-ManagementPolicies' - params: { - storageAccountName: storageAccount.name - rules: managementPolicyRules ?? [] +module storageAccount_managementPolicies 'management-policy/main.bicep' = + if (!empty(managementPolicyRules ?? [])) { + name: '${uniqueString(deployment().name, location)}-Storage-ManagementPolicies' + params: { + storageAccountName: storageAccount.name + rules: managementPolicyRules ?? [] + } + dependsOn: [ + storageAccount_blobServices // To ensure the lastAccessTimeTrackingPolicy is set first (if used in rule) + ] } - dependsOn: [ - storageAccount_blobServices // To ensure the lastAccessTimeTrackingPolicy is set first (if used in rule) - ] -} // SFTP user settings -module storageAccount_localUsers 'local-user/main.bicep' = [for (localUser, index) in localUsers: { - name: '${uniqueString(deployment().name, location)}-Storage-LocalUsers-${index}' - params: { - storageAccountName: storageAccount.name - name: localUser.name - hasSshKey: localUser.hasSshKey - hasSshPassword: localUser.hasSshPassword - permissionScopes: localUser.permissionScopes - hasSharedKey: localUser.?hasSharedKey - homeDirectory: localUser.?homeDirectory - sshAuthorizedKeys: localUser.?sshAuthorizedKeys +module storageAccount_localUsers 'local-user/main.bicep' = [ + for (localUser, index) in localUsers: { + name: '${uniqueString(deployment().name, location)}-Storage-LocalUsers-${index}' + params: { + storageAccountName: storageAccount.name + name: localUser.name + hasSshKey: localUser.hasSshKey + hasSshPassword: localUser.hasSshPassword + permissionScopes: localUser.permissionScopes + hasSharedKey: localUser.?hasSharedKey + homeDirectory: localUser.?homeDirectory + sshAuthorizedKeys: localUser.?sshAuthorizedKeys + } } -}] +] // Containers -module storageAccount_blobServices 'blob-service/main.bicep' = if (!empty(blobServices)) { - name: '${uniqueString(deployment().name, location)}-Storage-BlobServices' - params: { - storageAccountName: storageAccount.name - containers: blobServices.?containers - automaticSnapshotPolicyEnabled: blobServices.?automaticSnapshotPolicyEnabled - changeFeedEnabled: blobServices.?changeFeedEnabled - changeFeedRetentionInDays: blobServices.?changeFeedRetentionInDays - containerDeleteRetentionPolicyEnabled: blobServices.?containerDeleteRetentionPolicyEnabled - containerDeleteRetentionPolicyDays: blobServices.?containerDeleteRetentionPolicyDays - containerDeleteRetentionPolicyAllowPermanentDelete: blobServices.?containerDeleteRetentionPolicyAllowPermanentDelete - corsRules: blobServices.?corsRules - defaultServiceVersion: blobServices.?defaultServiceVersion - deleteRetentionPolicyAllowPermanentDelete: blobServices.?deleteRetentionPolicyAllowPermanentDelete - deleteRetentionPolicyEnabled: blobServices.?deleteRetentionPolicyEnabled - deleteRetentionPolicyDays: blobServices.?deleteRetentionPolicyDays - isVersioningEnabled: blobServices.?isVersioningEnabled - lastAccessTimeTrackingPolicyEnabled: blobServices.?lastAccessTimeTrackingPolicyEnabled - restorePolicyEnabled: blobServices.?restorePolicyEnabled - restorePolicyDays: blobServices.?restorePolicyDays - diagnosticSettings: blobServices.?diagnosticSettings +module storageAccount_blobServices 'blob-service/main.bicep' = + if (!empty(blobServices)) { + name: '${uniqueString(deployment().name, location)}-Storage-BlobServices' + params: { + storageAccountName: storageAccount.name + containers: blobServices.?containers + automaticSnapshotPolicyEnabled: blobServices.?automaticSnapshotPolicyEnabled + changeFeedEnabled: blobServices.?changeFeedEnabled + changeFeedRetentionInDays: blobServices.?changeFeedRetentionInDays + containerDeleteRetentionPolicyEnabled: blobServices.?containerDeleteRetentionPolicyEnabled + containerDeleteRetentionPolicyDays: blobServices.?containerDeleteRetentionPolicyDays + containerDeleteRetentionPolicyAllowPermanentDelete: blobServices.?containerDeleteRetentionPolicyAllowPermanentDelete + corsRules: blobServices.?corsRules + defaultServiceVersion: blobServices.?defaultServiceVersion + deleteRetentionPolicyAllowPermanentDelete: blobServices.?deleteRetentionPolicyAllowPermanentDelete + deleteRetentionPolicyEnabled: blobServices.?deleteRetentionPolicyEnabled + deleteRetentionPolicyDays: blobServices.?deleteRetentionPolicyDays + isVersioningEnabled: blobServices.?isVersioningEnabled + lastAccessTimeTrackingPolicyEnabled: blobServices.?lastAccessTimeTrackingPolicyEnabled + restorePolicyEnabled: blobServices.?restorePolicyEnabled + restorePolicyDays: blobServices.?restorePolicyDays + diagnosticSettings: blobServices.?diagnosticSettings + } } -} // File Shares -module storageAccount_fileServices 'file-service/main.bicep' = if (!empty(fileServices)) { - name: '${uniqueString(deployment().name, location)}-Storage-FileServices' - params: { - storageAccountName: storageAccount.name - diagnosticSettings: fileServices.?diagnosticSettings - protocolSettings: fileServices.?protocolSettings - shareDeleteRetentionPolicy: fileServices.?shareDeleteRetentionPolicy - shares: fileServices.?shares +module storageAccount_fileServices 'file-service/main.bicep' = + if (!empty(fileServices)) { + name: '${uniqueString(deployment().name, location)}-Storage-FileServices' + params: { + storageAccountName: storageAccount.name + diagnosticSettings: fileServices.?diagnosticSettings + protocolSettings: fileServices.?protocolSettings + shareDeleteRetentionPolicy: fileServices.?shareDeleteRetentionPolicy + shares: fileServices.?shares + } } -} // Queue -module storageAccount_queueServices 'queue-service/main.bicep' = if (!empty(queueServices)) { - name: '${uniqueString(deployment().name, location)}-Storage-QueueServices' - params: { - storageAccountName: storageAccount.name - diagnosticSettings: queueServices.?diagnosticSettings - queues: queueServices.?queues +module storageAccount_queueServices 'queue-service/main.bicep' = + if (!empty(queueServices)) { + name: '${uniqueString(deployment().name, location)}-Storage-QueueServices' + params: { + storageAccountName: storageAccount.name + diagnosticSettings: queueServices.?diagnosticSettings + queues: queueServices.?queues + } } -} // Table -module storageAccount_tableServices 'table-service/main.bicep' = if (!empty(tableServices)) { - name: '${uniqueString(deployment().name, location)}-Storage-TableServices' - params: { - storageAccountName: storageAccount.name - diagnosticSettings: tableServices.?diagnosticSettings - tables: tableServices.?tables +module storageAccount_tableServices 'table-service/main.bicep' = + if (!empty(tableServices)) { + name: '${uniqueString(deployment().name, location)}-Storage-TableServices' + params: { + storageAccountName: storageAccount.name + diagnosticSettings: tableServices.?diagnosticSettings + tables: tableServices.?tables + } } -} @description('The resource ID of the deployed storage account.') output resourceId string = storageAccount.id @@ -489,7 +619,9 @@ output name string = storageAccount.name output resourceGroupName string = resourceGroup().name @description('The primary blob endpoint reference if blob services are deployed.') -output primaryBlobEndpoint string = !empty(blobServices) && contains(blobServices, 'containers') ? reference('Microsoft.Storage/storageAccounts/${storageAccount.name}', '2019-04-01').primaryEndpoints.blob : '' +output primaryBlobEndpoint string = !empty(blobServices) && contains(blobServices, 'containers') + ? reference('Microsoft.Storage/storageAccounts/${storageAccount.name}', '2019-04-01').primaryEndpoints.blob + : '' @description('The principal ID of the system assigned identity.') output systemAssignedMIPrincipalId string = storageAccount.?identity.?principalId ?? '' @@ -551,7 +683,15 @@ type networkAclsType = { }[]? @description('Required. Specifies whether traffic is bypassed for Logging/Metrics/AzureServices. Possible values are any combination of Logging,Metrics,AzureServices (For example, "Logging, Metrics"), or None to bypass none of those traffics.') - bypass: ('None' | 'AzureServices' | 'Logging' | 'Metrics' | 'AzureServices, Logging' | 'AzureServices, Metrics' | 'AzureServices, Logging, Metrics' | 'Logging, Metrics') + bypass: ( + | 'None' + | 'AzureServices' + | 'Logging' + | 'Metrics' + | 'AzureServices, Logging' + | 'AzureServices, Metrics' + | 'AzureServices, Logging, Metrics' + | 'Logging, Metrics') @description('Optional. Sets the virtual network rules.') virtualNetworkRules: array? @@ -561,7 +701,7 @@ type networkAclsType = { @description('Required. Specifies the default action of allow or deny when no other rules match.') defaultAction: ('Allow' | 'Deny') -} +}? type privateEndpointType = { @description('Optional. The name of the private endpoint.') diff --git a/avm/res/storage/storage-account/management-policy/main.json b/avm/res/storage/storage-account/management-policy/main.json index 3e1730f09b..323df90a49 100644 --- a/avm/res/storage/storage-account/management-policy/main.json +++ b/avm/res/storage/storage-account/management-policy/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "774635646248081518" + "version": "0.26.54.24096", + "templateHash": "14052382142427178929" }, "name": "Storage Account Management Policies", "description": "This module deploys a Storage Account Management Policy.", diff --git a/avm/res/storage/storage-account/queue-service/main.json b/avm/res/storage/storage-account/queue-service/main.json index aae35c5012..ea2dd644a3 100644 --- a/avm/res/storage/storage-account/queue-service/main.json +++ b/avm/res/storage/storage-account/queue-service/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14446905482734328346" + "version": "0.26.54.24096", + "templateHash": "13677013226831946461" }, "name": "Storage Account Queue Services", "description": "This module deploys a Storage Account Queue Service.", @@ -250,8 +250,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "12411465246702614738" + "version": "0.26.54.24096", + "templateHash": "17219066722763101567" }, "name": "Storage Account Queues", "description": "This module deploys a Storage Account Queue.", 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 6ad5c15435..981f57b5d0 100644 --- a/avm/res/storage/storage-account/queue-service/queue/main.json +++ b/avm/res/storage/storage-account/queue-service/queue/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "12411465246702614738" + "version": "0.26.54.24096", + "templateHash": "17219066722763101567" }, "name": "Storage Account Queues", "description": "This module deploys a Storage Account Queue.", diff --git a/avm/res/storage/storage-account/table-service/main.json b/avm/res/storage/storage-account/table-service/main.json index 4b2089447c..bb058e623a 100644 --- a/avm/res/storage/storage-account/table-service/main.json +++ b/avm/res/storage/storage-account/table-service/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14471460242481977546" + "version": "0.26.54.24096", + "templateHash": "17373442840517371502" }, "name": "Storage Account Table Services", "description": "This module deploys a Storage Account Table Service.", @@ -247,8 +247,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "8824223095963877860" + "version": "0.26.54.24096", + "templateHash": "10226619499666007193" }, "name": "Storage Account Table", "description": "This module deploys a Storage Account Table.", 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 c87d417e99..1ba6eab43d 100644 --- a/avm/res/storage/storage-account/table-service/table/main.json +++ b/avm/res/storage/storage-account/table-service/table/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "8824223095963877860" + "version": "0.26.54.24096", + "templateHash": "10226619499666007193" }, "name": "Storage Account Table", "description": "This module deploys a Storage Account Table.", diff --git a/avm/res/storage/storage-account/tests/e2e/defaults/main.test.bicep b/avm/res/storage/storage-account/tests/e2e/defaults/main.test.bicep index db5eb11bf1..31e888a7ff 100644 --- a/avm/res/storage/storage-account/tests/e2e/defaults/main.test.bicep +++ b/avm/res/storage/storage-account/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,18 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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' - allowBlobPublicAccess: false +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + allowBlobPublicAccess: false + location: resourceLocation + networkAcls: { + defaultAction: 'Allow' + bypass: 'AzureServices' + } + } } -}] +] diff --git a/avm/res/synapse/private-link-hub/main.bicep b/avm/res/synapse/private-link-hub/main.bicep index 22d0d278ce..dd36ffbce2 100644 --- a/avm/res/synapse/private-link-hub/main.bicep +++ b/avm/res/synapse/private-link-hub/main.bicep @@ -27,27 +27,34 @@ 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.synapse-privatelinkhub.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.synapse-privatelinkhub.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource privateLinkHub 'Microsoft.Synapse/privateLinkHubs@2021-06-01' = { name: name @@ -56,72 +63,91 @@ resource privateLinkHub 'Microsoft.Synapse/privateLinkHubs@2021-06-01' = { } // Resource Lock -resource privateLinkHub_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.' +resource privateLinkHub_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: privateLinkHub } - scope: privateLinkHub -} // RBAC -resource privateLinkHub_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(privateLinkHub.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource privateLinkHub_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(privateLinkHub.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: privateLinkHub } - scope: privateLinkHub -}] +] // Private Endpoints -module privateLinkHub_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-PrivateLinkHub-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(privateLinkHub.id, '/'))}-${privateEndpoint.?service ?? 'web'}-${index}' - privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(privateLinkHub.id, '/'))}-${privateEndpoint.?service ?? 'web'}-${index}' - properties: { - privateLinkServiceId: privateLinkHub.id - groupIds: [ - privateEndpoint.?service ?? 'web' +module privateLinkHub_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-PrivateLinkHub-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(privateLinkHub.id, '/'))}-${privateEndpoint.?service ?? 'web'}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(privateLinkHub.id, '/'))}-${privateEndpoint.?service ?? 'web'}-${index}' + properties: { + privateLinkServiceId: privateLinkHub.id + groupIds: [ + privateEndpoint.?service ?? 'web' + ] + } + } ] - } - } - ] : null - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(privateLinkHub.id, '/'))}-${privateEndpoint.?service ?? 'web'}-${index}' - properties: { - privateLinkServiceId: privateLinkHub.id - groupIds: [ - privateEndpoint.?service ?? 'web' + : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(privateLinkHub.id, '/'))}-${privateEndpoint.?service ?? 'web'}-${index}' + properties: { + privateLinkServiceId: privateLinkHub.id + groupIds: [ + privateEndpoint.?service ?? 'web' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] +] @description('The resource ID of the deployed Synapse Private Link Hub.') output resourceId string = privateLinkHub.id diff --git a/avm/res/synapse/private-link-hub/main.json b/avm/res/synapse/private-link-hub/main.json index d0134ae735..4f2a9e3f8d 100644 --- a/avm/res/synapse/private-link-hub/main.json +++ b/avm/res/synapse/private-link-hub/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16624127378809450653" + "version": "0.26.54.24096", + "templateHash": "1037376719472164263" }, "name": "Azure Synapse Analytics", "description": "This module deploys an Azure Synapse Analytics (Private Link Hub).", diff --git a/avm/res/synapse/private-link-hub/tests/e2e/defaults/main.test.bicep b/avm/res/synapse/private-link-hub/tests/e2e/defaults/main.test.bicep index c726100b1d..6287d99a6c 100644 --- a/avm/res/synapse/private-link-hub/tests/e2e/defaults/main.test.bicep +++ b/avm/res/synapse/private-link-hub/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 +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 + } } -}] +] diff --git a/avm/res/synapse/private-link-hub/tests/e2e/max/main.test.bicep b/avm/res/synapse/private-link-hub/tests/e2e/max/main.test.bicep index 26749a1732..314df85fbd 100644 --- a/avm/res/synapse/private-link-hub/tests/e2e/max/main.test.bicep +++ b/avm/res/synapse/private-link-hub/tests/e2e/max/main.test.bicep @@ -47,54 +47,56 @@ 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 - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId - } - ] - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +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 + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - roleDefinitionIdOrName: '/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c' - principalType: 'ServicePrincipal' + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + } + ] + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + { + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + roleDefinitionIdOrName: '/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c' + principalType: 'ServicePrincipal' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/synapse/private-link-hub/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/synapse/private-link-hub/tests/e2e/waf-aligned/dependencies.bicep index d7fa917088..6f194062be 100644 --- a/avm/res/synapse/private-link-hub/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/synapse/private-link-hub/tests/e2e/waf-aligned/dependencies.bicep @@ -61,4 +61,3 @@ output subnetResourceId string = virtualNetwork.properties.subnets[0].id @description('The resource ID of the created Private DNS Zone.') output privateDNSZoneResourceId string = privateDNSZone.id - diff --git a/avm/res/synapse/private-link-hub/tests/e2e/waf-aligned/main.test.bicep b/avm/res/synapse/private-link-hub/tests/e2e/waf-aligned/main.test.bicep index 7a5577e6b5..bbbdccf99e 100644 --- a/avm/res/synapse/private-link-hub/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/synapse/private-link-hub/tests/e2e/waf-aligned/main.test.bicep @@ -46,33 +46,35 @@ 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 - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - service: 'Web' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +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 + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + service: 'Web' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/synapse/workspace/integration-runtime/main.bicep b/avm/res/synapse/workspace/integration-runtime/main.bicep index 2734626027..081805a6ba 100644 --- a/avm/res/synapse/workspace/integration-runtime/main.bicep +++ b/avm/res/synapse/workspace/integration-runtime/main.bicep @@ -25,16 +25,18 @@ resource workspace 'Microsoft.Synapse/workspaces@2021-06-01' existing = { resource integrationRuntime 'Microsoft.Synapse/workspaces/integrationRuntimes@2021-06-01' = { name: name parent: workspace - properties: type == 'Managed' ? { - type: type - managedVirtualNetwork: { - referenceName: 'default' - type: 'ManagedVirtualNetworkReference' - } - typeProperties: typeProperties - } : { - type: type - } + properties: type == 'Managed' + ? { + type: type + managedVirtualNetwork: { + referenceName: 'default' + type: 'ManagedVirtualNetworkReference' + } + typeProperties: typeProperties + } + : { + type: type + } } @description('The name of the Resource Group the Integration Runtime was created in.') diff --git a/avm/res/synapse/workspace/integration-runtime/main.json b/avm/res/synapse/workspace/integration-runtime/main.json index 97a5e64866..6ed516e1b3 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.25.53.49325", - "templateHash": "7739107907804712060" + "version": "0.26.54.24096", + "templateHash": "3692817517911366371" }, "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 b966f02678..bd04f8389c 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.25.53.49325", - "templateHash": "29131182338463302" + "version": "0.26.54.24096", + "templateHash": "4754954307876642999" }, "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 13c505992a..137294985f 100644 --- a/avm/res/synapse/workspace/main.bicep +++ b/avm/res/synapse/workspace/main.bicep @@ -93,11 +93,19 @@ param diagnosticSettings diagnosticSettingType // Variables -var cmkUserAssignedIdentityAsArray = !empty(customerManagedKey.?userAssignedIdentityResourceId ?? []) ? [ customerManagedKey.?userAssignedIdentityResourceId ] : [] +var cmkUserAssignedIdentityAsArray = !empty(customerManagedKey.?userAssignedIdentityResourceId ?? []) + ? [customerManagedKey.?userAssignedIdentityResourceId] + : [] -var userAssignedIdentitiesUnion = !empty(managedIdentities) ? union(managedIdentities.?userAssignedResourceIds ?? [], cmkUserAssignedIdentityAsArray) : cmkUserAssignedIdentityAsArray +var userAssignedIdentitiesUnion = !empty(managedIdentities) + ? union(managedIdentities.?userAssignedResourceIds ?? [], cmkUserAssignedIdentityAsArray) + : cmkUserAssignedIdentityAsArray -var formattedUserAssignedIdentities = reduce(map((userAssignedIdentitiesUnion ?? []), (id) => { '${id}': {} }), {}, (cur, next) => union(cur, next)) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } +var formattedUserAssignedIdentities = reduce( + map((userAssignedIdentitiesUnion ?? []), (id) => { '${id}': {} }), + {}, + (cur, next) => union(cur, next) +) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } var identity = { type: !empty(userAssignedIdentitiesUnion) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned' @@ -108,42 +116,61 @@ 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') - 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') - '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') + 'Resource Policy Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '36243c78-bf99-498c-9df9-86d9f8d28608' + ) + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.synapse-workspace.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.synapse-workspace.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} -resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId)) { - name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) - scope: resourceGroup(split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4]) - - resource cMKKey 'keys@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { - name: customerManagedKey.?keyName ?? 'dummyKey' +resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = + if (!empty(customerManagedKey.?keyVaultResourceId)) { + name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) + scope: resourceGroup( + split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], + split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4] + ) + + resource cMKKey 'keys@2023-02-01' existing = + if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { + name: customerManagedKey.?keyName ?? 'dummyKey' + } } -} -resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { - name: last(split(customerManagedKey.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) - scope: resourceGroup(split((customerManagedKey.?userAssignedIdentityResourceId ?? '//'), '/')[2], split((customerManagedKey.?userAssignedIdentityResourceId ?? '////'), '/')[4]) -} +resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = + if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { + name: last(split(customerManagedKey.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) + scope: resourceGroup( + split((customerManagedKey.?userAssignedIdentityResourceId ?? '//'), '/')[2], + split((customerManagedKey.?userAssignedIdentityResourceId ?? '////'), '/')[4] + ) + } resource workspace 'Microsoft.Synapse/workspaces@2021-06-01' = { name: name @@ -152,39 +179,49 @@ resource workspace 'Microsoft.Synapse/workspaces@2021-06-01' = { tags: tags properties: { azureADOnlyAuthentication: azureADOnlyAuthentication ? azureADOnlyAuthentication : null - cspWorkspaceAdminProperties: !empty(initialWorkspaceAdminObjectID) ? { - initialWorkspaceAdminObjectId: initialWorkspaceAdminObjectID - } : null + cspWorkspaceAdminProperties: !empty(initialWorkspaceAdminObjectID) + ? { + initialWorkspaceAdminObjectId: initialWorkspaceAdminObjectID + } + : null defaultDataLakeStorage: { resourceId: defaultDataLakeStorageAccountResourceId accountUrl: 'https://${last(split(defaultDataLakeStorageAccountResourceId, '/'))!}.dfs.${environment().suffixes.storage}' filesystem: defaultDataLakeStorageFilesystem createManagedPrivateEndpoint: managedVirtualNetwork ? defaultDataLakeStorageCreateManagedPrivateEndpoint : null } - encryption: !empty(customerManagedKey) ? { - cmk: { - kekIdentity: !empty(customerManagedKey.?userAssignedIdentityResourceId) ? { - userAssignedIdentity: cMKUserAssignedIdentity.id - } : { - useSystemAssignedIdentity: empty(customerManagedKey.?userAssignedIdentityResourceId) - } - key: { - keyVaultUrl: cMKKeyVault::cMKKey.properties.keyUri - name: customerManagedKey!.keyName + encryption: !empty(customerManagedKey) + ? { + cmk: { + kekIdentity: !empty(customerManagedKey.?userAssignedIdentityResourceId) + ? { + userAssignedIdentity: cMKUserAssignedIdentity.id + } + : { + useSystemAssignedIdentity: empty(customerManagedKey.?userAssignedIdentityResourceId) + } + key: { + keyVaultUrl: cMKKeyVault::cMKKey.properties.keyUri + name: customerManagedKey!.keyName + } + } } - } - } : null + : null managedResourceGroupName: !empty(managedResourceGroupName) ? managedResourceGroupName : null managedVirtualNetwork: managedVirtualNetwork ? 'default' : null - managedVirtualNetworkSettings: managedVirtualNetwork ? { - allowedAadTenantIdsForLinking: allowedAadTenantIdsForLinking - linkedAccessCheckOnTargetResource: linkedAccessCheckOnTargetResource - preventDataExfiltration: preventDataExfiltration - } : null + managedVirtualNetworkSettings: managedVirtualNetwork + ? { + allowedAadTenantIdsForLinking: allowedAadTenantIdsForLinking + linkedAccessCheckOnTargetResource: linkedAccessCheckOnTargetResource + preventDataExfiltration: preventDataExfiltration + } + : null publicNetworkAccess: managedVirtualNetwork ? publicNetworkAccess : null - purviewConfiguration: !empty(purviewResourceID) ? { - purviewResourceId: purviewResourceID - } : null + purviewConfiguration: !empty(purviewResourceID) + ? { + purviewResourceId: purviewResourceID + } + : null sqlAdministratorLogin: sqlAdministratorLogin sqlAdministratorLoginPassword: !empty(sqlAdministratorLoginPassword) ? sqlAdministratorLoginPassword : null workspaceRepositoryConfiguration: workspaceRepositoryConfiguration @@ -192,129 +229,161 @@ resource workspace 'Microsoft.Synapse/workspaces@2021-06-01' = { } // Workspace integration runtimes -module synapse_integrationRuntimes 'integration-runtime/main.bicep' = [for (integrationRuntime, index) in integrationRuntimes: { - name: '${uniqueString(deployment().name, location)}-Synapse-IntegrationRuntime-${index}' - params: { - workspaceName: workspace.name - name: integrationRuntime.name - type: integrationRuntime.type - typeProperties: contains(integrationRuntime, 'typeProperties') ? integrationRuntime.typeProperties : {} +module synapse_integrationRuntimes 'integration-runtime/main.bicep' = [ + for (integrationRuntime, index) in integrationRuntimes: { + name: '${uniqueString(deployment().name, location)}-Synapse-IntegrationRuntime-${index}' + params: { + workspaceName: workspace.name + name: integrationRuntime.name + type: integrationRuntime.type + typeProperties: contains(integrationRuntime, 'typeProperties') ? integrationRuntime.typeProperties : {} + } } -}] +] // Workspace encryption with customer managed keys // - Assign Synapse Workspace MSI access to encryption key -module workspace_cmk_rbac 'modules/nested_cmkRbac.bicep' = if (encryptionActivateWorkspace) { - name: '${workspace.name}-cmk-rbac' - params: { - workspaceIndentityPrincipalId: workspace.identity.principalId - keyvaultName: !empty(customerManagedKey.?keyVaultResourceId) ? cMKKeyVault.name : '' - usesRbacAuthorization: !empty(customerManagedKey.?keyVaultResourceId) ? cMKKeyVault.properties.enableRbacAuthorization : true +module workspace_cmk_rbac 'modules/nested_cmkRbac.bicep' = + if (encryptionActivateWorkspace) { + name: '${workspace.name}-cmk-rbac' + params: { + workspaceIndentityPrincipalId: workspace.identity.principalId + keyvaultName: !empty(customerManagedKey.?keyVaultResourceId) ? cMKKeyVault.name : '' + usesRbacAuthorization: !empty(customerManagedKey.?keyVaultResourceId) + ? cMKKeyVault.properties.enableRbacAuthorization + : true + } + scope: encryptionActivateWorkspace + ? resourceGroup( + split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], + split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4] + ) + : resourceGroup() } - scope: encryptionActivateWorkspace ? resourceGroup(split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4]) : resourceGroup() -} // - Workspace encryption - Activate Workspace -module workspace_key 'key/main.bicep' = if (encryptionActivateWorkspace) { - name: '${workspace.name}-cmk-activation' - params: { - name: customerManagedKey!.keyName - isActiveCMK: true - keyVaultResourceId: cMKKeyVault.id - workspaceName: workspace.name +module workspace_key 'key/main.bicep' = + if (encryptionActivateWorkspace) { + name: '${workspace.name}-cmk-activation' + params: { + name: customerManagedKey!.keyName + isActiveCMK: true + keyVaultResourceId: cMKKeyVault.id + workspaceName: workspace.name + } + dependsOn: [ + workspace_cmk_rbac + ] } - dependsOn: [ - workspace_cmk_rbac - ] -} // Resource Lock -resource workspace_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.' +resource workspace_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: workspace } - scope: workspace -} // RBAC -resource workspace_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(workspace.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource workspace_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(workspace.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: workspace } - scope: workspace -}] +] // Endpoints -module workspace_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-workspace-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(workspace.id, '/'))}-${privateEndpoint.service}-${index}' - privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(workspace.id, '/'))}-${privateEndpoint.service}-${index}' - properties: { - privateLinkServiceId: workspace.id - groupIds: [ - privateEndpoint.service +module workspace_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-workspace-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(workspace.id, '/'))}-${privateEndpoint.service}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(workspace.id, '/'))}-${privateEndpoint.service}-${index}' + properties: { + privateLinkServiceId: workspace.id + groupIds: [ + privateEndpoint.service + ] + } + } ] - } - } - ] : null - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(workspace.id, '/'))}-${privateEndpoint.service}-${index}' - properties: { - privateLinkServiceId: workspace.id - groupIds: [ - privateEndpoint.service + : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(workspace.id, '/'))}-${privateEndpoint.service}-${index}' + properties: { + privateLinkServiceId: workspace.id + groupIds: [ + privateEndpoint.service + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] +] // Diagnostics Settings -resource workspace_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - logs: diagnosticSetting.?logCategoriesAndGroups ?? [ - { - categoryGroup: 'AllLogs' - enabled: true - } - ] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource workspace_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + logs: diagnosticSetting.?logCategoriesAndGroups ?? [ + { + categoryGroup: 'AllLogs' + enabled: true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: workspace } - scope: workspace -}] +] @description('The resource ID of the deployed Synapse Workspace.') output resourceID string = workspace.id diff --git a/avm/res/synapse/workspace/main.json b/avm/res/synapse/workspace/main.json index 102e84b052..0e1f785400 100644 --- a/avm/res/synapse/workspace/main.json +++ b/avm/res/synapse/workspace/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "199483993688319459" + "version": "0.26.54.24096", + "templateHash": "12255523377827341539" }, "name": "Synapse Workspaces", "description": "This module deploys a Synapse Workspace.", @@ -797,8 +797,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "7739107907804712060" + "version": "0.26.54.24096", + "templateHash": "3692817517911366371" }, "name": "Synapse Workspace Integration Runtimes", "description": "This module deploys a Synapse Workspace Integration Runtime.", @@ -895,8 +895,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "16862202180408198277" + "version": "0.26.54.24096", + "templateHash": "11661011043333744116" } }, "parameters": { @@ -983,8 +983,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "29131182338463302" + "version": "0.26.54.24096", + "templateHash": "4754954307876642999" }, "name": "Synapse Workspaces Keys", "description": "This module deploys a Synapse Workspaces Key.", diff --git a/avm/res/synapse/workspace/tests/e2e/defaults/dependencies.bicep b/avm/res/synapse/workspace/tests/e2e/defaults/dependencies.bicep index b057b0b981..11a476b1e7 100644 --- a/avm/res/synapse/workspace/tests/e2e/defaults/dependencies.bicep +++ b/avm/res/synapse/workspace/tests/e2e/defaults/dependencies.bicep @@ -5,23 +5,23 @@ param location string = resourceGroup().location param storageAccountName string resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' = { - name: storageAccountName - location: location - sku: { - name: 'Standard_LRS' - } - kind: 'StorageV2' - properties: { - isHnsEnabled: true - } + name: storageAccountName + location: location + sku: { + name: 'Standard_LRS' + } + kind: 'StorageV2' + properties: { + isHnsEnabled: true + } - resource blobService 'blobServices@2022-09-01' = { - name: 'default' + resource blobService 'blobServices@2022-09-01' = { + name: 'default' - resource container 'containers@2022-09-01' = { - name: 'synapsews' - } + resource container 'containers@2022-09-01' = { + name: 'synapsews' } + } } @description('The resource ID of the created Storage Account.') diff --git a/avm/res/synapse/workspace/tests/e2e/defaults/main.test.bicep b/avm/res/synapse/workspace/tests/e2e/defaults/main.test.bicep index 5b96756401..50adf1a478 100644 --- a/avm/res/synapse/workspace/tests/e2e/defaults/main.test.bicep +++ b/avm/res/synapse/workspace/tests/e2e/defaults/main.test.bicep @@ -45,17 +45,19 @@ 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 - defaultDataLakeStorageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId - defaultDataLakeStorageFilesystem: nestedDependencies.outputs.storageContainerName - sqlAdministratorLogin: 'synwsadmin' +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 + defaultDataLakeStorageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + defaultDataLakeStorageFilesystem: nestedDependencies.outputs.storageContainerName + sqlAdministratorLogin: 'synwsadmin' + } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/synapse/workspace/tests/e2e/encrwsai/dependencies.bicep b/avm/res/synapse/workspace/tests/e2e/encrwsai/dependencies.bicep index ef593e0e43..6d7a736f40 100644 --- a/avm/res/synapse/workspace/tests/e2e/encrwsai/dependencies.bicep +++ b/avm/res/synapse/workspace/tests/e2e/encrwsai/dependencies.bicep @@ -8,49 +8,49 @@ param keyVaultName string param storageAccountName string resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { - name: keyVaultName - location: location - properties: { - sku: { - family: 'A' - name: 'standard' - } - tenantId: tenant().tenantId - enablePurgeProtection: true - softDeleteRetentionInDays: 7 - enabledForTemplateDeployment: true - enabledForDiskEncryption: true - enabledForDeployment: true - enableRbacAuthorization: true - accessPolicies: [] + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' } + tenantId: tenant().tenantId + enablePurgeProtection: true + softDeleteRetentionInDays: 7 + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } - resource key 'keys@2022-07-01' = { - name: 'keyEncryptionKey' - properties: { - kty: 'RSA' - } + resource key 'keys@2022-07-01' = { + name: 'keyEncryptionKey' + properties: { + kty: 'RSA' } + } } resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' = { - name: storageAccountName - location: location - sku: { - name: 'Standard_LRS' - } - kind: 'StorageV2' - properties: { - isHnsEnabled: true - } + name: storageAccountName + location: location + sku: { + name: 'Standard_LRS' + } + kind: 'StorageV2' + properties: { + isHnsEnabled: true + } - resource blobService 'blobServices@2022-09-01' = { - name: 'default' + resource blobService 'blobServices@2022-09-01' = { + name: 'default' - resource container 'containers@2022-09-01' = { - name: 'synapsews' - } + resource container 'containers@2022-09-01' = { + name: 'synapsews' } + } } @description('The resource ID of the created Key Vault.') diff --git a/avm/res/synapse/workspace/tests/e2e/encrwsai/main.test.bicep b/avm/res/synapse/workspace/tests/e2e/encrwsai/main.test.bicep index 1099ded9b2..4f63a039ef 100644 --- a/avm/res/synapse/workspace/tests/e2e/encrwsai/main.test.bicep +++ b/avm/res/synapse/workspace/tests/e2e/encrwsai/main.test.bicep @@ -50,22 +50,24 @@ 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' - defaultDataLakeStorageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId - defaultDataLakeStorageFilesystem: nestedDependencies.outputs.storageContainerName - sqlAdministratorLogin: 'synwsadmin' - customerManagedKey: { - keyName: nestedDependencies.outputs.keyVaultEncryptionKeyName - keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + defaultDataLakeStorageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + defaultDataLakeStorageFilesystem: nestedDependencies.outputs.storageContainerName + sqlAdministratorLogin: 'synwsadmin' + customerManagedKey: { + keyName: nestedDependencies.outputs.keyVaultEncryptionKeyName + keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + } + encryptionActivateWorkspace: true + location: resourceLocation } - encryptionActivateWorkspace: true - location: resourceLocation + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/synapse/workspace/tests/e2e/encrwuai/dependencies.bicep b/avm/res/synapse/workspace/tests/e2e/encrwuai/dependencies.bicep index 6faa37afac..04f775602e 100644 --- a/avm/res/synapse/workspace/tests/e2e/encrwuai/dependencies.bicep +++ b/avm/res/synapse/workspace/tests/e2e/encrwuai/dependencies.bicep @@ -11,64 +11,67 @@ param keyVaultName string param storageAccountName string resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location + name: managedIdentityName + location: location } resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { - name: keyVaultName - location: location - properties: { - sku: { - family: 'A' - name: 'standard' - } - tenantId: tenant().tenantId - enablePurgeProtection: true - softDeleteRetentionInDays: 7 - enabledForTemplateDeployment: true - enabledForDiskEncryption: true - enabledForDeployment: true - enableRbacAuthorization: true - accessPolicies: [] + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' } + tenantId: tenant().tenantId + enablePurgeProtection: true + softDeleteRetentionInDays: 7 + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } - resource key 'keys@2022-07-01' = { - name: 'keyEncryptionKey' - properties: { - kty: 'RSA' - } + resource key 'keys@2022-07-01' = { + name: 'keyEncryptionKey' + properties: { + kty: 'RSA' } + } } resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid('msi-${keyVault::key.id}-${location}-${managedIdentity.id}-Key-Reader-RoleAssignment') - scope: keyVault::key - properties: { - principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User - principalType: 'ServicePrincipal' - } + name: guid('msi-${keyVault::key.id}-${location}-${managedIdentity.id}-Key-Reader-RoleAssignment') + scope: keyVault::key + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '12338af0-0e69-4776-bea7-57ae8d297424' + ) // Key Vault Crypto User + principalType: 'ServicePrincipal' + } } resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' = { - name: storageAccountName - location: location - sku: { - name: 'Standard_LRS' - } - kind: 'StorageV2' - properties: { - isHnsEnabled: true - } + name: storageAccountName + location: location + sku: { + name: 'Standard_LRS' + } + kind: 'StorageV2' + properties: { + isHnsEnabled: true + } - resource blobService 'blobServices@2022-09-01' = { - name: 'default' + resource blobService 'blobServices@2022-09-01' = { + name: 'default' - resource container 'containers@2022-09-01' = { - name: 'synapsews' - } + resource container 'containers@2022-09-01' = { + name: 'synapsews' } + } } @description('The resource ID of the created Managed Identity.') diff --git a/avm/res/synapse/workspace/tests/e2e/encrwuai/main.test.bicep b/avm/res/synapse/workspace/tests/e2e/encrwuai/main.test.bicep index b1905e7fd0..373831bb01 100644 --- a/avm/res/synapse/workspace/tests/e2e/encrwuai/main.test.bicep +++ b/avm/res/synapse/workspace/tests/e2e/encrwuai/main.test.bicep @@ -51,22 +51,24 @@ 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 - defaultDataLakeStorageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId - defaultDataLakeStorageFilesystem: nestedDependencies.outputs.storageContainerName - sqlAdministratorLogin: 'synwsadmin' - customerManagedKey: { - keyName: nestedDependencies.outputs.keyVaultEncryptionKeyName - keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - userAssignedIdentityResourceId: 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 + defaultDataLakeStorageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + defaultDataLakeStorageFilesystem: nestedDependencies.outputs.storageContainerName + sqlAdministratorLogin: 'synwsadmin' + customerManagedKey: { + keyName: nestedDependencies.outputs.keyVaultEncryptionKeyName + keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + userAssignedIdentityResourceId: nestedDependencies.outputs.managedIdentityResourceId + } } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/synapse/workspace/tests/e2e/managedvnet/dependencies.bicep b/avm/res/synapse/workspace/tests/e2e/managedvnet/dependencies.bicep index b057b0b981..11a476b1e7 100644 --- a/avm/res/synapse/workspace/tests/e2e/managedvnet/dependencies.bicep +++ b/avm/res/synapse/workspace/tests/e2e/managedvnet/dependencies.bicep @@ -5,23 +5,23 @@ param location string = resourceGroup().location param storageAccountName string resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' = { - name: storageAccountName - location: location - sku: { - name: 'Standard_LRS' - } - kind: 'StorageV2' - properties: { - isHnsEnabled: true - } + name: storageAccountName + location: location + sku: { + name: 'Standard_LRS' + } + kind: 'StorageV2' + properties: { + isHnsEnabled: true + } - resource blobService 'blobServices@2022-09-01' = { - name: 'default' + resource blobService 'blobServices@2022-09-01' = { + name: 'default' - resource container 'containers@2022-09-01' = { - name: 'synapsews' - } + resource container 'containers@2022-09-01' = { + name: 'synapsews' } + } } @description('The resource ID of the created Storage Account.') diff --git a/avm/res/synapse/workspace/tests/e2e/managedvnet/main.test.bicep b/avm/res/synapse/workspace/tests/e2e/managedvnet/main.test.bicep index 4cbe44aa95..1ae5fd451d 100644 --- a/avm/res/synapse/workspace/tests/e2e/managedvnet/main.test.bicep +++ b/avm/res/synapse/workspace/tests/e2e/managedvnet/main.test.bicep @@ -45,22 +45,24 @@ 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 - defaultDataLakeStorageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId - defaultDataLakeStorageFilesystem: nestedDependencies.outputs.storageContainerName - sqlAdministratorLogin: 'synwsadmin' - managedVirtualNetwork: true - preventDataExfiltration: true - allowedAadTenantIdsForLinking: [ - tenant().tenantId +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 + defaultDataLakeStorageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + defaultDataLakeStorageFilesystem: nestedDependencies.outputs.storageContainerName + sqlAdministratorLogin: 'synwsadmin' + managedVirtualNetwork: true + preventDataExfiltration: true + allowedAadTenantIdsForLinking: [ + tenant().tenantId + ] + } + dependsOn: [ + nestedDependencies ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/synapse/workspace/tests/e2e/max/main.test.bicep b/avm/res/synapse/workspace/tests/e2e/max/main.test.bicep index b798023efb..682ca135f8 100644 --- a/avm/res/synapse/workspace/tests/e2e/max/main.test.bicep +++ b/avm/res/synapse/workspace/tests/e2e/max/main.test.bicep @@ -61,110 +61,115 @@ 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 - defaultDataLakeStorageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId - defaultDataLakeStorageFilesystem: nestedDependencies.outputs.storageContainerName - sqlAdministratorLogin: 'synwsadmin' - initialWorkspaceAdminObjectID: nestedDependencies.outputs.managedIdentityPrincipalId - managedIdentities: { - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - 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' - } - ] - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId +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 + defaultDataLakeStorageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + defaultDataLakeStorageFilesystem: nestedDependencies.outputs.storageContainerName + sqlAdministratorLogin: 'synwsadmin' + initialWorkspaceAdminObjectID: nestedDependencies.outputs.managedIdentityPrincipalId + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId ] - service: 'SQL' - subnetResourceId: nestedDependencies.outputs.customSubnet1ResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } } - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - service: 'SQL' - subnetResourceId: nestedDependencies.outputs.customSubnet2ResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Owner' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' } - } - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - service: 'SqlOnDemand' - subnetResourceId: nestedDependencies.outputs.customSubnet1ResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + { + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' } - } - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - service: 'Dev' - subnetResourceId: nestedDependencies.outputs.customSubnet1ResourceId - } - ] - managedVirtualNetwork: true - integrationRuntimes: [ - { - type: 'SelfHosted' - name: 'shir01' - } - ] - diagnosticSettings: [ - { - name: 'customSetting' - logCategoriesAndGroups: [ - { - category: 'SynapseRbacOperations' + { + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + service: 'SQL' + subnetResourceId: nestedDependencies.outputs.customSubnet1ResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - { - category: 'SynapseLinkEvent' + } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + service: 'SQL' + subnetResourceId: nestedDependencies.outputs.customSubnet2ResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } + } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + service: 'SqlOnDemand' + subnetResourceId: nestedDependencies.outputs.customSubnet1ResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + service: 'Dev' + subnetResourceId: nestedDependencies.outputs.customSubnet1ResourceId + } + ] + managedVirtualNetwork: true + integrationRuntimes: [ + { + type: 'SelfHosted' + name: 'shir01' + } + ] + diagnosticSettings: [ + { + name: 'customSetting' + logCategoriesAndGroups: [ + { + category: 'SynapseRbacOperations' + } + { + category: 'SynapseLinkEvent' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + } + dependsOn: [ + nestedDependencies + diagnosticDependencies ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/synapse/workspace/tests/e2e/waf-aligned/main.test.bicep b/avm/res/synapse/workspace/tests/e2e/waf-aligned/main.test.bicep index f47275aa9e..d6a7bc47fb 100644 --- a/avm/res/synapse/workspace/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/synapse/workspace/tests/e2e/waf-aligned/main.test.bicep @@ -60,61 +60,63 @@ 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 - defaultDataLakeStorageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId - defaultDataLakeStorageFilesystem: nestedDependencies.outputs.storageContainerName - sqlAdministratorLogin: 'synwsadmin' - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - service: 'SQL' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } - ] - managedVirtualNetwork: true - integrationRuntimes: [ - { - type: 'SelfHosted' - name: 'shir01' - } - ] - diagnosticSettings: [ - { - name: 'customSetting' - logCategoriesAndGroups: [ - { - category: 'SynapseRbacOperations' - } - { - category: 'SynapseLinkEvent' +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 + defaultDataLakeStorageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + defaultDataLakeStorageFilesystem: nestedDependencies.outputs.storageContainerName + sqlAdministratorLogin: 'synwsadmin' + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + service: 'SQL' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + managedVirtualNetwork: true + integrationRuntimes: [ + { + type: 'SelfHosted' + name: 'shir01' + } + ] + diagnosticSettings: [ + { + name: 'customSetting' + logCategoriesAndGroups: [ + { + category: 'SynapseRbacOperations' + } + { + category: 'SynapseLinkEvent' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/virtual-machine-images/image-template/main.bicep b/avm/res/virtual-machine-images/image-template/main.bicep index d7a74cd99f..4c46be1680 100644 --- a/avm/res/virtual-machine-images/image-template/main.bicep +++ b/avm/res/virtual-machine-images/image-template/main.bicep @@ -60,34 +60,45 @@ param managedIdentities managedIdentitiesType var identity = { type: 'UserAssigned' - userAssignedIdentities: reduce(map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), {}, (cur, next) => union(cur, next)) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } + userAssignedIdentities: reduce( + map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), + {}, + (cur, next) => union(cur, next) + ) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } } 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + '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' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.virtualmachineimages-imagetemplate.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.virtualmachineimages-imagetemplate.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource imageTemplate 'Microsoft.VirtualMachineImages/imageTemplates@2022-02-14' = { #disable-next-line use-stable-resource-identifiers // Disabling as ImageTemplates are not idempotent and hence always must have new name @@ -101,68 +112,92 @@ resource imageTemplate 'Microsoft.VirtualMachineImages/imageTemplates@2022-02-14 vmSize: vmSize osDiskSizeGB: osDiskSizeGB userAssignedIdentities: vmUserAssignedIdentities - vnetConfig: !empty(subnetResourceId) ? { - subnetId: subnetResourceId - } : null + vnetConfig: !empty(subnetResourceId) + ? { + subnetId: subnetResourceId + } + : null } source: imageSource customize: customizationSteps stagingResourceGroup: stagingResourceGroup - distribute: [for distribution in distributions: union({ - type: distribution.type - artifactTags: distribution.?artifactTags ?? { - sourceType: imageSource.type - sourcePublisher: imageSource.?publisher - sourceOffer: imageSource.?offer - sourceSku: imageSource.?sku - sourceVersion: imageSource.?version - sourceImageId: imageSource.?imageId - sourceImageVersionID: imageSource.?imageVersionID - creationTime: baseTime - } - }, - (distribution.type == 'ManagedImage' ? { - runOutputName: distribution.?runOutputName ?? '${distribution.imageName}-${baseTime}-ManagedImage' - location: distribution.?location ?? location - #disable-next-line use-resource-id-functions // Disabling rule as this is an input parameter that is used inside an array. - imageId: distribution.?imageResourceId ?? '${subscription().id}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Compute/images/${distribution.imageName}-${baseTime}' - } : {}), - (distribution.type == 'SharedImage' ? { - runOutputName: distribution.?runOutputName ?? (!empty(distribution.?sharedImageGalleryImageDefinitionResourceId) ? '${last(split((distribution.sharedImageGalleryImageDefinitionResourceId ?? '/'), '/'))}-SharedImage' : 'SharedImage') - galleryImageId: !empty(distribution.?sharedImageGalleryImageDefinitionTargetVersion) ? '${distribution.sharedImageGalleryImageDefinitionResourceId}/versions/${distribution.sharedImageGalleryImageDefinitionTargetVersion}' : distribution.sharedImageGalleryImageDefinitionResourceId - excludeFromLatest: distribution.?excludeFromLatest ?? false - replicationRegions: distribution.?replicationRegions ?? [ location ] - storageAccountType: distribution.?storageAccountType ?? 'Standard_LRS' - } : {}), - (distribution.type == 'VHD' ? { - runOutputName: distribution.?runOutputName ?? '${distribution.imageName}-VHD' - } : {}) - )] + distribute: [ + for distribution in distributions: union( + { + type: distribution.type + artifactTags: distribution.?artifactTags ?? { + sourceType: imageSource.type + sourcePublisher: imageSource.?publisher + sourceOffer: imageSource.?offer + sourceSku: imageSource.?sku + sourceVersion: imageSource.?version + sourceImageId: imageSource.?imageId + sourceImageVersionID: imageSource.?imageVersionID + creationTime: baseTime + } + }, + (distribution.type == 'ManagedImage' + ? { + runOutputName: distribution.?runOutputName ?? '${distribution.imageName}-${baseTime}-ManagedImage' + location: distribution.?location ?? location + #disable-next-line use-resource-id-functions // Disabling rule as this is an input parameter that is used inside an array. + imageId: distribution.?imageResourceId ?? '${subscription().id}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Compute/images/${distribution.imageName}-${baseTime}' + } + : {}), + (distribution.type == 'SharedImage' + ? { + runOutputName: distribution.?runOutputName ?? (!empty(distribution.?sharedImageGalleryImageDefinitionResourceId) + ? '${last(split((distribution.sharedImageGalleryImageDefinitionResourceId ?? '/'), '/'))}-SharedImage' + : 'SharedImage') + galleryImageId: !empty(distribution.?sharedImageGalleryImageDefinitionTargetVersion) + ? '${distribution.sharedImageGalleryImageDefinitionResourceId}/versions/${distribution.sharedImageGalleryImageDefinitionTargetVersion}' + : distribution.sharedImageGalleryImageDefinitionResourceId + excludeFromLatest: distribution.?excludeFromLatest ?? false + replicationRegions: distribution.?replicationRegions ?? [location] + storageAccountType: distribution.?storageAccountType ?? 'Standard_LRS' + } + : {}), + (distribution.type == 'VHD' + ? { + runOutputName: distribution.?runOutputName ?? '${distribution.imageName}-VHD' + } + : {}) + ) + ] } } -resource imageTemplate_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.' +resource imageTemplate_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: imageTemplate } - scope: imageTemplate -} -resource imageTemplate_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(imageTemplate.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource imageTemplate_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(imageTemplate.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: imageTemplate } - scope: imageTemplate -}] +] @description('The resource ID of the image template.') output resourceId string = imageTemplate.id @@ -226,7 +261,6 @@ type managedIdentitiesType = { type distributionType = sharedImageDistributionType | managedImageDistributionType | unManagedDistributionType type sharedImageDistributionType = { - @description('Optional. The name to be used for the associated RunOutput. If not provided, a name will be calculated.') runOutputName: string? @@ -253,7 +287,6 @@ type sharedImageDistributionType = { } type unManagedDistributionType = { - @description('Required. The type of distribution.') type: 'VHD' @@ -268,7 +301,6 @@ type unManagedDistributionType = { } type managedImageDistributionType = { - @description('Required. The type of distribution.') type: 'ManagedImage' diff --git a/avm/res/virtual-machine-images/image-template/main.json b/avm/res/virtual-machine-images/image-template/main.json index cbc35f7506..e2bef8c3df 100644 --- a/avm/res/virtual-machine-images/image-template/main.json +++ b/avm/res/virtual-machine-images/image-template/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "13080829112167347263" + "version": "0.26.54.24096", + "templateHash": "4620280027037163005" }, "name": "Virtual Machine Image Templates", "description": "This module deploys a Virtual Machine Image Template that can be consumed by Azure Image Builder (AIB).", diff --git a/avm/res/virtual-machine-images/image-template/tests/e2e/defaults/dependencies.bicep b/avm/res/virtual-machine-images/image-template/tests/e2e/defaults/dependencies.bicep index 5de1a5cc92..1808563dfe 100644 --- a/avm/res/virtual-machine-images/image-template/tests/e2e/defaults/dependencies.bicep +++ b/avm/res/virtual-machine-images/image-template/tests/e2e/defaults/dependencies.bicep @@ -12,7 +12,10 @@ resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018- resource msi_roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { name: guid(resourceGroup().id, 'Contributor', managedIdentityName) properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + roleDefinitionId: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b24988ac-6180-42a0-ab88-20f7382dd24c' + ) // Contributor principalId: managedIdentity.properties.principalId principalType: 'ServicePrincipal' } diff --git a/avm/res/virtual-machine-images/image-template/tests/e2e/max/dependencies.bicep b/avm/res/virtual-machine-images/image-template/tests/e2e/max/dependencies.bicep index 3333148724..036e72fb96 100644 --- a/avm/res/virtual-machine-images/image-template/tests/e2e/max/dependencies.bicep +++ b/avm/res/virtual-machine-images/image-template/tests/e2e/max/dependencies.bicep @@ -190,7 +190,11 @@ resource imageManagedIdentityOperatorRbac 'Microsoft.Authorization/roleAssignmen // Allow Deployment Script MSI to access storage account container to upload files resource storageContributorRbac 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(assetsStorageAccount::blobService::container.id, storageBlobDataContributorRole.id, imageManagedIdentity.id) + name: guid( + assetsStorageAccount::blobService::container.id, + storageBlobDataContributorRole.id, + imageManagedIdentity.id + ) scope: assetsStorageAccount::blobService::container properties: { roleDefinitionId: storageBlobDataContributorRole.id @@ -226,7 +230,13 @@ resource dsStorageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = { { // Allow deployment script to use storage account for private networking of container instance action: 'Allow' - id: resourceId(subscription().subscriptionId, resourceGroup().name, 'Microsoft.Network/virtualNetworks/subnets', virtualNetwork.name, deploymentScriptSubnetName) + id: resourceId( + subscription().subscriptionId, + resourceGroup().name, + 'Microsoft.Network/virtualNetworks/subnets', + virtualNetwork.name, + deploymentScriptSubnetName + ) } ] } @@ -278,7 +288,13 @@ resource assetsStorageAccount_upload 'Microsoft.Resources/deploymentScripts@2023 containerSettings: { subnetIds: [ { - id: resourceId(subscription().subscriptionId, resourceGroup().name, 'Microsoft.Network/virtualNetworks/subnets', virtualNetwork.name, deploymentScriptSubnetName) + id: resourceId( + subscription().subscriptionId, + resourceGroup().name, + 'Microsoft.Network/virtualNetworks/subnets', + virtualNetwork.name, + deploymentScriptSubnetName + ) } ] } diff --git a/avm/res/virtual-machine-images/image-template/tests/e2e/max/main.test.bicep b/avm/res/virtual-machine-images/image-template/tests/e2e/max/main.test.bicep index 8de9388d3d..2bd4869dd5 100644 --- a/avm/res/virtual-machine-images/image-template/tests/e2e/max/main.test.bicep +++ b/avm/res/virtual-machine-images/image-template/tests/e2e/max/main.test.bicep @@ -134,7 +134,10 @@ module testDeployment '../../../main.bicep' = { principalType: 'ServicePrincipal' } { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) principalId: nestedDependencies.outputs.managedIdentityPrincipalId principalType: 'ServicePrincipal' } diff --git a/avm/res/web/serverfarm/main.bicep b/avm/res/web/serverfarm/main.bicep index 89ca6b812f..7cff682e16 100644 --- a/avm/res/web/serverfarm/main.bicep +++ b/avm/res/web/serverfarm/main.bicep @@ -9,7 +9,7 @@ param name string @description('Required. Defines the name, tier, size, family and capacity of the App Service Plan.') @metadata({ - example: ''' + example: ''' { name: 'P1v3' tier: 'Premium' @@ -18,8 +18,7 @@ param name string capacity: 3 } ''' - } -) +}) param sku object @description('Optional. Location for all resources.') @@ -83,29 +82,42 @@ 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') - 'Web Plan Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b') - 'Website Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772') + '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' + ) + 'Web Plan Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b' + ) + 'Website Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'de139f84-1756-47ae-9be6-808fbbe84772' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.web-serverfarm.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.web-serverfarm.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource appServicePlan 'Microsoft.Web/serverfarms@2022-09-01' = { name: name @@ -115,9 +127,11 @@ resource appServicePlan 'Microsoft.Web/serverfarms@2022-09-01' = { sku: sku properties: { workerTierName: workerTierName - hostingEnvironmentProfile: !empty(appServiceEnvironmentId) ? { - id: appServiceEnvironmentId - } : null + hostingEnvironmentProfile: !empty(appServiceEnvironmentId) + ? { + id: appServiceEnvironmentId + } + : null perSiteScaling: perSiteScaling maximumElasticWorkerCount: maximumElasticWorkerCount reserved: reserved @@ -127,46 +141,59 @@ resource appServicePlan 'Microsoft.Web/serverfarms@2022-09-01' = { } } -resource appServicePlan_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource appServicePlan_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: appServicePlan } - scope: appServicePlan -}] - -resource appServicePlan_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.' +] + +resource appServicePlan_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: appServicePlan } - scope: appServicePlan -} -resource appServicePlan_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(appServicePlan.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource appServicePlan_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(appServicePlan.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: appServicePlan } - scope: appServicePlan -}] +] @description('The resource group the app service plan was deployed into.') output resourceGroupName string = resourceGroup().name diff --git a/avm/res/web/serverfarm/main.json b/avm/res/web/serverfarm/main.json index 6ccd7bb609..bf40400bed 100644 --- a/avm/res/web/serverfarm/main.json +++ b/avm/res/web/serverfarm/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "14257048735375797880" + "version": "0.26.54.24096", + "templateHash": "12495804892051718765" }, "name": "App Service Plan", "description": "This module deploys an App Service Plan.", diff --git a/avm/res/web/serverfarm/tests/e2e/defaults/main.test.bicep b/avm/res/web/serverfarm/tests/e2e/defaults/main.test.bicep index 01e3c49e5a..9f2ffe8e94 100644 --- a/avm/res/web/serverfarm/tests/e2e/defaults/main.test.bicep +++ b/avm/res/web/serverfarm/tests/e2e/defaults/main.test.bicep @@ -39,18 +39,20 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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: tempLocation - sku: { - name: 'P1v3' - tier: 'Premium' - size: 'P1v3' - family: 'P' - capacity: 3 +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: tempLocation + sku: { + name: 'P1v3' + tier: 'Premium' + size: 'P1v3' + family: 'P' + capacity: 3 + } } } -}] +] diff --git a/avm/res/web/serverfarm/tests/e2e/max/main.test.bicep b/avm/res/web/serverfarm/tests/e2e/max/main.test.bicep index 6a48f83bc9..5451356bd1 100644 --- a/avm/res/web/serverfarm/tests/e2e/max/main.test.bicep +++ b/avm/res/web/serverfarm/tests/e2e/max/main.test.bicep @@ -60,61 +60,66 @@ 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: tempLocation - sku: { - name: 'P1v3' - tier: 'Premium' - size: 'P1v3' - family: 'P' - capacity: 3 - } - perSiteScaling: true - zoneRedundant: true - kind: 'App' - lock: { - name: 'lock' - kind: 'CanNotDelete' - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' +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: tempLocation + sku: { + name: 'P1v3' + tier: 'Premium' + size: 'P1v3' + family: 'P' + capacity: 3 } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + perSiteScaling: true + zoneRedundant: true + kind: 'App' + lock: { + name: 'lock' + kind: 'CanNotDelete' } - { - 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' + Role: 'DeploymentValidation' } - ] - diagnosticSettings: [ - { - name: 'customSetting${serviceShort}' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] + 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${serviceShort}' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + } } -}] +] diff --git a/avm/res/web/serverfarm/tests/e2e/waf-aligned/main.test.bicep b/avm/res/web/serverfarm/tests/e2e/waf-aligned/main.test.bicep index 0cf59b787c..5cd23e57c9 100644 --- a/avm/res/web/serverfarm/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/web/serverfarm/tests/e2e/waf-aligned/main.test.bicep @@ -51,43 +51,45 @@ 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: tempLocation - sku: { - name: 'P1v3' - tier: 'Premium' - size: 'P1v3' - family: 'P' - capacity: 3 - } - zoneRedundant: true - kind: 'App' - lock: { - name: 'lock' - kind: 'CanNotDelete' - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - diagnosticSettings: [ - { - name: 'customSetting${serviceShort}' - 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: tempLocation + sku: { + name: 'P1v3' + tier: 'Premium' + size: 'P1v3' + family: 'P' + capacity: 3 + } + zoneRedundant: true + kind: 'App' + lock: { + name: 'lock' + kind: 'CanNotDelete' } - ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + diagnosticSettings: [ + { + name: 'customSetting${serviceShort}' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + } } -}] +] diff --git a/avm/res/web/site/README.md b/avm/res/web/site/README.md index 150a304f80..a1d528472c 100644 --- a/avm/res/web/site/README.md +++ b/avm/res/web/site/README.md @@ -664,7 +664,6 @@ module site 'br/public:avm/res/web/site:' = { healthCheckPath: '/healthz' } } - } ``` @@ -1164,7 +1163,7 @@ This instance deploys the module as a Linux Web App with the minimum set of requ ```bicep module site 'br/public:avm/res/web/site:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-wswalmin' + name: 'siteDeployment' params: { // Required parameters kind: 'app,linux' @@ -1220,7 +1219,7 @@ This instance deploys the module asa Linux Web App with most of its features ena ```bicep module site 'br/public:avm/res/web/site:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-wswalmax' + name: 'siteDeployment' params: { // Required parameters kind: 'app,linux' diff --git a/avm/res/web/site/config--appsettings/main.bicep b/avm/res/web/site/config--appsettings/main.bicep index 573c274a95..bb782168aa 100644 --- a/avm/res/web/site/config--appsettings/main.bicep +++ b/avm/res/web/site/config--appsettings/main.bicep @@ -28,16 +28,22 @@ param appInsightResourceId string? @description('Optional. The app settings key-value pairs except for AzureWebJobsStorage, AzureWebJobsDashboard, APPINSIGHTS_INSTRUMENTATIONKEY and APPLICATIONINSIGHTS_CONNECTION_STRING.') param appSettingsKeyValuePairs object? -var azureWebJobsValues = !empty(storageAccountResourceId) && !(storageAccountUseIdentityAuthentication) ? { - AzureWebJobsStorage: 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${storageAccount.listKeys().keys[0].value};' -} : !empty(storageAccountResourceId) && storageAccountUseIdentityAuthentication ? union( - { AzureWebJobsStorage__accountName: storageAccount.name }, - { AzureWebJobsStorage__blobServiceUri: storageAccount.properties.primaryEndpoints.blob } -) : {} - -var appInsightsValues = !empty(appInsightResourceId) ? { - APPLICATIONINSIGHTS_CONNECTION_STRING: appInsight.properties.ConnectionString -} : {} +var azureWebJobsValues = !empty(storageAccountResourceId) && !(storageAccountUseIdentityAuthentication) + ? { + AzureWebJobsStorage: 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${storageAccount.listKeys().keys[0].value};' + } + : !empty(storageAccountResourceId) && storageAccountUseIdentityAuthentication + ? union( + { AzureWebJobsStorage__accountName: storageAccount.name }, + { AzureWebJobsStorage__blobServiceUri: storageAccount.properties.primaryEndpoints.blob } + ) + : {} + +var appInsightsValues = !empty(appInsightResourceId) + ? { + APPLICATIONINSIGHTS_CONNECTION_STRING: appInsight.properties.ConnectionString + } + : {} var expandedAppSettings = union(appSettingsKeyValuePairs ?? {}, azureWebJobsValues, appInsightsValues) @@ -45,15 +51,20 @@ resource app 'Microsoft.Web/sites@2022-09-01' existing = { name: appName } -resource appInsight 'Microsoft.Insights/components@2020-02-02' existing = if (!empty(appInsightResourceId)) { - name: last(split(appInsightResourceId ?? 'dummyName', '/')) - scope: resourceGroup(split(appInsightResourceId ?? '//', '/')[2], split(appInsightResourceId ?? '////', '/')[4]) -} - -resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' existing = if (!empty(storageAccountResourceId)) { - name: last(split(storageAccountResourceId ?? 'dummyName', '/')) - scope: resourceGroup(split(storageAccountResourceId ?? '//', '/')[2], split(storageAccountResourceId ?? '////', '/')[4]) -} +resource appInsight 'Microsoft.Insights/components@2020-02-02' existing = + if (!empty(appInsightResourceId)) { + name: last(split(appInsightResourceId ?? 'dummyName', '/')) + scope: resourceGroup(split(appInsightResourceId ?? '//', '/')[2], split(appInsightResourceId ?? '////', '/')[4]) + } + +resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' existing = + if (!empty(storageAccountResourceId)) { + name: last(split(storageAccountResourceId ?? 'dummyName', '/')) + scope: resourceGroup( + split(storageAccountResourceId ?? '//', '/')[2], + split(storageAccountResourceId ?? '////', '/')[4] + ) + } resource appSettings 'Microsoft.Web/sites/config@2022-09-01' = { name: 'appsettings' 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 7b6a7f1182..7b64d67dc9 100644 --- a/avm/res/web/site/hybrid-connection-namespace/relay/main.bicep +++ b/avm/res/web/site/hybrid-connection-namespace/relay/main.bicep @@ -28,7 +28,13 @@ resource hybridConnectionRelay 'Microsoft.Web/sites/hybridConnectionNamespaces/r name: '${appName}/${namespace.name}/${namespace::hybridConnection.name}' properties: { serviceBusNamespace: namespace.name - serviceBusSuffix: split(substring(namespace.properties.serviceBusEndpoint, indexOf(namespace.properties.serviceBusEndpoint, '.servicebus')), ':')[0] + serviceBusSuffix: split( + substring( + namespace.properties.serviceBusEndpoint, + indexOf(namespace.properties.serviceBusEndpoint, '.servicebus') + ), + ':' + )[0] relayName: namespace::hybridConnection.name relayArmUri: namespace::hybridConnection.id hostname: split(json(namespace::hybridConnection.properties.userMetadata)[0].value, ':')[0] diff --git a/avm/res/web/site/main.bicep b/avm/res/web/site/main.bicep index a4a63bc236..c0571f9765 100644 --- a/avm/res/web/site/main.bicep +++ b/avm/res/web/site/main.bicep @@ -157,41 +157,65 @@ param hybridConnectionRelays array? ]) param publicNetworkAccess string? -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 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 builtInRoleNames = { - 'App Compliance Automation Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f37683f-2463-46b6-9ce7-9b788b988ba2') + 'App Compliance Automation Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '0f37683f-2463-46b6-9ce7-9b788b988ba2' + ) 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') - 'Web Plan Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b') - 'Website Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772') + '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' + ) + 'Web Plan Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b' + ) + 'Website Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'de139f84-1756-47ae-9be6-808fbbe84772' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.web-site.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.web-site.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource app 'Microsoft.Web/sites@2022-09-01' = { name: name @@ -203,9 +227,11 @@ resource app 'Microsoft.Web/sites@2022-09-01' = { serverFarmId: serverFarmResourceId clientAffinityEnabled: clientAffinityEnabled httpsOnly: httpsOnly - hostingEnvironmentProfile: !empty(appServiceEnvironmentResourceId) ? { - id: appServiceEnvironmentResourceId - } : null + hostingEnvironmentProfile: !empty(appServiceEnvironmentResourceId) + ? { + id: appServiceEnvironmentResourceId + } + : null storageAccountRequired: storageAccountRequired keyVaultReferenceIdentity: keyVaultAccessIdentityResourceId virtualNetworkSubnetId: virtualNetworkSubnetId @@ -221,7 +247,9 @@ resource app 'Microsoft.Web/sites@2022-09-01' = { hostNameSslStates: hostNameSslStates hyperV: hyperV redundancyMode: redundancyMode - publicNetworkAccess: !empty(publicNetworkAccess) ? any(publicNetworkAccess) : (!empty(privateEndpoints) ? 'Disabled' : 'Enabled') + publicNetworkAccess: !empty(publicNetworkAccess) + ? any(publicNetworkAccess) + : (!empty(privateEndpoints) ? 'Disabled' : 'Enabled') vnetContentShareEnabled: vnetContentShareEnabled vnetImagePullEnabled: vnetImagePullEnabled vnetRouteAllEnabled: vnetRouteAllEnabled @@ -229,181 +257,216 @@ resource app 'Microsoft.Web/sites@2022-09-01' = { } } -module app_appsettings 'config--appsettings/main.bicep' = if (!empty(appSettingsKeyValuePairs)) { - name: '${uniqueString(deployment().name, location)}-Site-Config-AppSettings' - params: { - appName: app.name - kind: kind - storageAccountResourceId: storageAccountResourceId - storageAccountUseIdentityAuthentication: storageAccountUseIdentityAuthentication - appInsightResourceId: appInsightResourceId - appSettingsKeyValuePairs: appSettingsKeyValuePairs +module app_appsettings 'config--appsettings/main.bicep' = + if (!empty(appSettingsKeyValuePairs)) { + name: '${uniqueString(deployment().name, location)}-Site-Config-AppSettings' + params: { + appName: app.name + kind: kind + storageAccountResourceId: storageAccountResourceId + storageAccountUseIdentityAuthentication: storageAccountUseIdentityAuthentication + appInsightResourceId: appInsightResourceId + appSettingsKeyValuePairs: appSettingsKeyValuePairs + } } -} -module app_authsettingsv2 'config--authsettingsv2/main.bicep' = if (!empty(authSettingV2Configuration)) { - name: '${uniqueString(deployment().name, location)}-Site-Config-AuthSettingsV2' - params: { - appName: app.name - kind: kind - authSettingV2Configuration: authSettingV2Configuration ?? {} +module app_authsettingsv2 'config--authsettingsv2/main.bicep' = + if (!empty(authSettingV2Configuration)) { + name: '${uniqueString(deployment().name, location)}-Site-Config-AuthSettingsV2' + params: { + appName: app.name + kind: kind + authSettingV2Configuration: authSettingV2Configuration ?? {} + } } -} @batchSize(1) -module app_slots 'slot/main.bicep' = [for (slot, index) in (slots ?? []): { - name: '${uniqueString(deployment().name, location)}-Slot-${slot.name}' - params: { - name: slot.name - appName: app.name - location: location - kind: kind - serverFarmResourceId: serverFarmResourceId - httpsOnly: slot.?httpsOnly ?? httpsOnly - appServiceEnvironmentResourceId: appServiceEnvironmentResourceId - clientAffinityEnabled: slot.?clientAffinityEnabled ?? clientAffinityEnabled - managedIdentities: slot.?managedIdentities ?? managedIdentities - keyVaultAccessIdentityResourceId: slot.?keyVaultAccessIdentityResourceId ?? keyVaultAccessIdentityResourceId - storageAccountRequired: slot.?storageAccountRequired ?? storageAccountRequired - virtualNetworkSubnetId: slot.?virtualNetworkSubnetId ?? virtualNetworkSubnetId - siteConfig: slot.?siteConfig ?? siteConfig - storageAccountResourceId: slot.?storageAccountResourceId ?? storageAccountResourceId - storageAccountUseIdentityAuthentication: slot.?storageAccountUseIdentityAuthentication ?? storageAccountUseIdentityAuthentication - appInsightResourceId: slot.?appInsightResourceId ?? appInsightResourceId - authSettingV2Configuration: slot.?authSettingV2Configuration ?? authSettingV2Configuration - diagnosticSettings: slot.?diagnosticSettings - roleAssignments: slot.?roleAssignments ?? roleAssignments - appSettingsKeyValuePairs: slot.?appSettingsKeyValuePairs ?? appSettingsKeyValuePairs - basicPublishingCredentialsPolicies: slot.?basicPublishingCredentialsPolicies ?? basicPublishingCredentialsPolicies - lock: slot.?lock ?? lock - privateEndpoints: slot.?privateEndpoints ?? [] - tags: slot.?tags ?? tags - clientCertEnabled: slot.?clientCertEnabled - clientCertExclusionPaths: slot.?clientCertExclusionPaths - clientCertMode: slot.?clientCertMode - cloningInfo: slot.?cloningInfo - containerSize: slot.?containerSize - customDomainVerificationId: slot.?customDomainVerificationId - dailyMemoryTimeQuota: slot.?dailyMemoryTimeQuota - enabled: slot.?enabled - enableTelemetry: slot.?enableTelemetry ?? enableTelemetry - hostNameSslStates: slot.?hostNameSslStates - hyperV: slot.?hyperV - publicNetworkAccess: slot.?publicNetworkAccess ?? ((!empty(slot.?privateEndpoints) || !empty(privateEndpoints)) ? 'Disabled' : 'Enabled') - redundancyMode: slot.?redundancyMode - vnetContentShareEnabled: slot.?vnetContentShareEnabled - vnetImagePullEnabled: slot.?vnetImagePullEnabled - vnetRouteAllEnabled: slot.?vnetRouteAllEnabled - hybridConnectionRelays: slot.?hybridConnectionRelays +module app_slots 'slot/main.bicep' = [ + for (slot, index) in (slots ?? []): { + name: '${uniqueString(deployment().name, location)}-Slot-${slot.name}' + params: { + name: slot.name + appName: app.name + location: location + kind: kind + serverFarmResourceId: serverFarmResourceId + httpsOnly: slot.?httpsOnly ?? httpsOnly + appServiceEnvironmentResourceId: appServiceEnvironmentResourceId + clientAffinityEnabled: slot.?clientAffinityEnabled ?? clientAffinityEnabled + managedIdentities: slot.?managedIdentities ?? managedIdentities + keyVaultAccessIdentityResourceId: slot.?keyVaultAccessIdentityResourceId ?? keyVaultAccessIdentityResourceId + storageAccountRequired: slot.?storageAccountRequired ?? storageAccountRequired + virtualNetworkSubnetId: slot.?virtualNetworkSubnetId ?? virtualNetworkSubnetId + siteConfig: slot.?siteConfig ?? siteConfig + storageAccountResourceId: slot.?storageAccountResourceId ?? storageAccountResourceId + storageAccountUseIdentityAuthentication: slot.?storageAccountUseIdentityAuthentication ?? storageAccountUseIdentityAuthentication + appInsightResourceId: slot.?appInsightResourceId ?? appInsightResourceId + authSettingV2Configuration: slot.?authSettingV2Configuration ?? authSettingV2Configuration + diagnosticSettings: slot.?diagnosticSettings + roleAssignments: slot.?roleAssignments ?? roleAssignments + appSettingsKeyValuePairs: slot.?appSettingsKeyValuePairs ?? appSettingsKeyValuePairs + basicPublishingCredentialsPolicies: slot.?basicPublishingCredentialsPolicies ?? basicPublishingCredentialsPolicies + lock: slot.?lock ?? lock + privateEndpoints: slot.?privateEndpoints ?? [] + tags: slot.?tags ?? tags + clientCertEnabled: slot.?clientCertEnabled + clientCertExclusionPaths: slot.?clientCertExclusionPaths + clientCertMode: slot.?clientCertMode + cloningInfo: slot.?cloningInfo + containerSize: slot.?containerSize + customDomainVerificationId: slot.?customDomainVerificationId + dailyMemoryTimeQuota: slot.?dailyMemoryTimeQuota + enabled: slot.?enabled + enableTelemetry: slot.?enableTelemetry ?? enableTelemetry + hostNameSslStates: slot.?hostNameSslStates + hyperV: slot.?hyperV + publicNetworkAccess: slot.?publicNetworkAccess ?? ((!empty(slot.?privateEndpoints) || !empty(privateEndpoints)) + ? 'Disabled' + : 'Enabled') + redundancyMode: slot.?redundancyMode + vnetContentShareEnabled: slot.?vnetContentShareEnabled + vnetImagePullEnabled: slot.?vnetImagePullEnabled + vnetRouteAllEnabled: slot.?vnetRouteAllEnabled + hybridConnectionRelays: slot.?hybridConnectionRelays + } } -}] - -module app_basicPublishingCredentialsPolicies 'basic-publishing-credentials-policy/main.bicep' = [for (basicPublishingCredentialsPolicy, index) in (basicPublishingCredentialsPolicies ?? []): { - name: '${uniqueString(deployment().name, location)}-Site-Publish-Cred-${index}' - params: { - webAppName: app.name - name: basicPublishingCredentialsPolicy.name - allow: basicPublishingCredentialsPolicy.?allow - location: location +] + +module app_basicPublishingCredentialsPolicies 'basic-publishing-credentials-policy/main.bicep' = [ + for (basicPublishingCredentialsPolicy, index) in (basicPublishingCredentialsPolicies ?? []): { + name: '${uniqueString(deployment().name, location)}-Site-Publish-Cred-${index}' + params: { + webAppName: app.name + name: basicPublishingCredentialsPolicy.name + allow: basicPublishingCredentialsPolicy.?allow + location: location + } } -}] - -module app_hybridConnectionRelays 'hybrid-connection-namespace/relay/main.bicep' = [for (hybridConnectionRelay, index) in (hybridConnectionRelays ?? []): { - name: '${uniqueString(deployment().name, location)}-HybridConnectionRelay-${index}' - params: { - hybridConnectionResourceId: hybridConnectionRelay.resourceId - appName: app.name - sendKeyName: hybridConnectionRelay.?sendKeyName +] + +module app_hybridConnectionRelays 'hybrid-connection-namespace/relay/main.bicep' = [ + for (hybridConnectionRelay, index) in (hybridConnectionRelays ?? []): { + name: '${uniqueString(deployment().name, location)}-HybridConnectionRelay-${index}' + params: { + hybridConnectionResourceId: hybridConnectionRelay.resourceId + appName: app.name + sendKeyName: hybridConnectionRelay.?sendKeyName + } } -}] +] -resource app_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.' +resource app_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: app } - scope: app -} -resource app_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource app_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: app } - scope: app -}] +] -resource app_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(app.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource app_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(app.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: app } - scope: app -}] - -module app_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-App-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(app.id, '/'))}-${privateEndpoint.?service ?? 'sites'}-${index}' - privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(app.id, '/'))}-${privateEndpoint.?service ?? 'sites'}-${index}' - properties: { - privateLinkServiceId: app.id - groupIds: [ - privateEndpoint.?service ?? 'sites' +] + +module app_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-App-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(app.id, '/'))}-${privateEndpoint.?service ?? 'sites'}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(app.id, '/'))}-${privateEndpoint.?service ?? 'sites'}-${index}' + properties: { + privateLinkServiceId: app.id + groupIds: [ + privateEndpoint.?service ?? 'sites' + ] + } + } ] - } - } - ] : null - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(app.id, '/'))}-${privateEndpoint.?service ?? 'sites'}-${index}' - properties: { - privateLinkServiceId: app.id - groupIds: [ - privateEndpoint.?service ?? 'sites' + : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(app.id, '/'))}-${privateEndpoint.?service ?? 'sites'}-${index}' + properties: { + privateLinkServiceId: app.id + groupIds: [ + privateEndpoint.?service ?? 'sites' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] +] @description('The name of the site.') output name string = app.name @@ -424,7 +487,9 @@ output resourceGroupName string = resourceGroup().name output systemAssignedMIPrincipalId string = app.?identity.?principalId ?? '' @description('The principal ID of the system assigned identity of slots.') -output slotSystemAssignedMIPrincipalIds array = [for (slot, index) in (slots ?? []): app_slots[index].outputs.systemAssignedMIPrincipalId] +output slotSystemAssignedMIPrincipalIds array = [ + for (slot, index) in (slots ?? []): app_slots[index].outputs.systemAssignedMIPrincipalId +] @description('The location the resource was deployed into.') output location string = app.location diff --git a/avm/res/web/site/slot/config--appsettings/main.bicep b/avm/res/web/site/slot/config--appsettings/main.bicep index 6572451c58..679037db56 100644 --- a/avm/res/web/site/slot/config--appsettings/main.bicep +++ b/avm/res/web/site/slot/config--appsettings/main.bicep @@ -31,16 +31,22 @@ param appInsightResourceId string? @description('Optional. The app settings key-value pairs except for AzureWebJobsStorage, AzureWebJobsDashboard, APPINSIGHTS_INSTRUMENTATIONKEY and APPLICATIONINSIGHTS_CONNECTION_STRING.') param appSettingsKeyValuePairs object? -var azureWebJobsValues = !empty(storageAccountResourceId) && !(storageAccountUseIdentityAuthentication) ? { - AzureWebJobsStorage: 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${storageAccount.listKeys().keys[0].value};' -} : !empty(storageAccountResourceId) && storageAccountUseIdentityAuthentication ? union( - { AzureWebJobsStorage__accountName: storageAccount.name }, - { AzureWebJobsStorage__blobServiceUri: storageAccount.properties.primaryEndpoints.blob } -) : {} - -var appInsightsValues = !empty(appInsightResourceId) ? { - APPLICATIONINSIGHTS_CONNECTION_STRING: appInsight.properties.ConnectionString -} : {} +var azureWebJobsValues = !empty(storageAccountResourceId) && !(storageAccountUseIdentityAuthentication) + ? { + AzureWebJobsStorage: 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${storageAccount.listKeys().keys[0].value};' + } + : !empty(storageAccountResourceId) && storageAccountUseIdentityAuthentication + ? union( + { AzureWebJobsStorage__accountName: storageAccount.name }, + { AzureWebJobsStorage__blobServiceUri: storageAccount.properties.primaryEndpoints.blob } + ) + : {} + +var appInsightsValues = !empty(appInsightResourceId) + ? { + APPLICATIONINSIGHTS_CONNECTION_STRING: appInsight.properties.ConnectionString + } + : {} var expandedAppSettings = union(appSettingsKeyValuePairs ?? {}, azureWebJobsValues, appInsightsValues) @@ -52,15 +58,20 @@ resource app 'Microsoft.Web/sites@2022-09-01' existing = { } } -resource appInsight 'Microsoft.Insights/components@2020-02-02' existing = if (!empty(appInsightResourceId)) { - name: last(split(appInsightResourceId ?? 'dummyName', '/')) - scope: resourceGroup(split(appInsightResourceId ?? '//', '/')[2], split(appInsightResourceId ?? '////', '/')[4]) -} +resource appInsight 'Microsoft.Insights/components@2020-02-02' existing = + if (!empty(appInsightResourceId)) { + name: last(split(appInsightResourceId ?? 'dummyName', '/')) + scope: resourceGroup(split(appInsightResourceId ?? '//', '/')[2], split(appInsightResourceId ?? '////', '/')[4]) + } -resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' existing = if (!empty(storageAccountResourceId)) { - name: last(split(storageAccountResourceId ?? 'dummyName', '/'))! - scope: resourceGroup(split(storageAccountResourceId ?? '//', '/')[2], split(storageAccountResourceId ?? '////', '/')[4]) -} +resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' existing = + if (!empty(storageAccountResourceId)) { + name: last(split(storageAccountResourceId ?? 'dummyName', '/'))! + scope: resourceGroup( + split(storageAccountResourceId ?? '//', '/')[2], + split(storageAccountResourceId ?? '////', '/')[4] + ) + } resource slotSettings 'Microsoft.Web/sites/slots/config@2022-09-01' = { name: 'appsettings' 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 5ffc44a797..6e85a49f08 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 @@ -31,7 +31,13 @@ resource hybridConnectionRelay 'Microsoft.Web/sites/slots/hybridConnectionNamesp name: '${appName}/${slotName}/${namespace.name}/${namespace::hybridConnection.name}' properties: { serviceBusNamespace: namespace.name - serviceBusSuffix: split(substring(namespace.properties.serviceBusEndpoint, indexOf(namespace.properties.serviceBusEndpoint, '.servicebus')), ':')[0] + serviceBusSuffix: split( + substring( + namespace.properties.serviceBusEndpoint, + indexOf(namespace.properties.serviceBusEndpoint, '.servicebus') + ), + ':' + )[0] relayName: namespace::hybridConnection.name relayArmUri: namespace::hybridConnection.id hostname: split(json(namespace::hybridConnection.properties.userMetadata)[0].value, ':')[0] diff --git a/avm/res/web/site/slot/main.bicep b/avm/res/web/site/slot/main.bicep index b5b5cf1354..209954c101 100644 --- a/avm/res/web/site/slot/main.bicep +++ b/avm/res/web/site/slot/main.bicep @@ -149,22 +149,45 @@ param vnetRouteAllEnabled bool = false @description('Optional. Names of hybrid connection relays to connect app with.') param hybridConnectionRelays array? -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 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 builtInRoleNames = { - 'App Compliance Automation Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f37683f-2463-46b6-9ce7-9b788b988ba2') + 'App Compliance Automation Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '0f37683f-2463-46b6-9ce7-9b788b988ba2' + ) 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') - 'Web Plan Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b') - 'Website Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772') + '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' + ) + 'Web Plan Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b' + ) + 'Website Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'de139f84-1756-47ae-9be6-808fbbe84772' + ) } resource app 'Microsoft.Web/sites@2021-03-01' existing = { @@ -182,9 +205,11 @@ resource slot 'Microsoft.Web/sites/slots@2022-09-01' = { serverFarmId: serverFarmResourceId clientAffinityEnabled: clientAffinityEnabled httpsOnly: httpsOnly - hostingEnvironmentProfile: !empty(appServiceEnvironmentResourceId) ? { - id: appServiceEnvironmentResourceId - } : null + hostingEnvironmentProfile: !empty(appServiceEnvironmentResourceId) + ? { + id: appServiceEnvironmentResourceId + } + : null storageAccountRequired: storageAccountRequired keyVaultReferenceIdentity: keyVaultAccessIdentityResourceId virtualNetworkSubnetId: virtualNetworkSubnetId @@ -207,136 +232,167 @@ resource slot 'Microsoft.Web/sites/slots@2022-09-01' = { } } -module slot_appsettings 'config--appsettings/main.bicep' = if (!empty(appSettingsKeyValuePairs)) { - name: '${uniqueString(deployment().name, location)}-Slot-${name}-Config-AppSettings' - params: { - slotName: slot.name - appName: app.name - kind: kind - storageAccountResourceId: storageAccountResourceId - storageAccountUseIdentityAuthentication: storageAccountUseIdentityAuthentication - appInsightResourceId: appInsightResourceId - appSettingsKeyValuePairs: appSettingsKeyValuePairs +module slot_appsettings 'config--appsettings/main.bicep' = + if (!empty(appSettingsKeyValuePairs)) { + name: '${uniqueString(deployment().name, location)}-Slot-${name}-Config-AppSettings' + params: { + slotName: slot.name + appName: app.name + kind: kind + storageAccountResourceId: storageAccountResourceId + storageAccountUseIdentityAuthentication: storageAccountUseIdentityAuthentication + appInsightResourceId: appInsightResourceId + appSettingsKeyValuePairs: appSettingsKeyValuePairs + } } -} -module slot_authsettingsv2 'config--authsettingsv2/main.bicep' = if (!empty(authSettingV2Configuration)) { - name: '${uniqueString(deployment().name, location)}-Slot-${name}-Config-AuthSettingsV2' - params: { - slotName: slot.name - appName: app.name - kind: kind - authSettingV2Configuration: authSettingV2Configuration ?? {} +module slot_authsettingsv2 'config--authsettingsv2/main.bicep' = + if (!empty(authSettingV2Configuration)) { + name: '${uniqueString(deployment().name, location)}-Slot-${name}-Config-AuthSettingsV2' + params: { + slotName: slot.name + appName: app.name + kind: kind + authSettingV2Configuration: authSettingV2Configuration ?? {} + } } -} -module slot_basicPublishingCredentialsPolicies 'basic-publishing-credentials-policy/main.bicep' = [for (basicPublishingCredentialsPolicy, index) in (basicPublishingCredentialsPolicies ?? []): { - name: '${uniqueString(deployment().name, location)}-Slot-Publish-Cred-${index}' - params: { - appName: app.name - slotName: slot.name - name: basicPublishingCredentialsPolicy.name - allow: basicPublishingCredentialsPolicy.?allow - location: location +module slot_basicPublishingCredentialsPolicies 'basic-publishing-credentials-policy/main.bicep' = [ + for (basicPublishingCredentialsPolicy, index) in (basicPublishingCredentialsPolicies ?? []): { + name: '${uniqueString(deployment().name, location)}-Slot-Publish-Cred-${index}' + params: { + appName: app.name + slotName: slot.name + name: basicPublishingCredentialsPolicy.name + allow: basicPublishingCredentialsPolicy.?allow + location: location + } } -}] -module slot_hybridConnectionRelays 'hybrid-connection-namespace/relay/main.bicep' = [for (hybridConnectionRelay, index) in (hybridConnectionRelays ?? []): { - name: '${uniqueString(deployment().name, location)}-Slot-HybridConnectionRelay-${index}' - params: { - hybridConnectionResourceId: hybridConnectionRelay.resourceId - appName: app.name - slotName: slot.name - sendKeyName: hybridConnectionRelay.?sendKeyName +] +module slot_hybridConnectionRelays 'hybrid-connection-namespace/relay/main.bicep' = [ + for (hybridConnectionRelay, index) in (hybridConnectionRelays ?? []): { + name: '${uniqueString(deployment().name, location)}-Slot-HybridConnectionRelay-${index}' + params: { + hybridConnectionResourceId: hybridConnectionRelay.resourceId + appName: app.name + slotName: slot.name + sendKeyName: hybridConnectionRelay.?sendKeyName + } } -}] +] -resource slot_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.' +resource slot_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: slot } - scope: slot -} -resource slot_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [for group in (diagnosticSetting.?metricCategories ?? [ { category: 'AllMetrics' } ]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - }] - logs: [for group in (diagnosticSetting.?logCategoriesAndGroups ?? [ { categoryGroup: 'allLogs' } ]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - }] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType +resource slot_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: slot } - scope: slot -}] +] -resource slot_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(slot.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource slot_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(slot.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: slot } - scope: slot -}] - -module slot_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-Slot-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(app.id, '/'))}-${name}-${privateEndpoint.?service ?? 'sites-${slot.name}'}-${index}' - privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(app.id, '/'))}-${privateEndpoint.?service ?? 'sites-${slot.name}'}-${index}' - properties: { - privateLinkServiceId: app.id // Must be set on the WebApp and not the slot - groupIds: [ - privateEndpoint.?service ?? 'sites-${slot.name}' // The required syntax to create the private endpoint for a specific slot +] + +module slot_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-Slot-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(app.id, '/'))}-${name}-${privateEndpoint.?service ?? 'sites-${slot.name}'}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(app.id, '/'))}-${privateEndpoint.?service ?? 'sites-${slot.name}'}-${index}' + properties: { + privateLinkServiceId: app.id // Must be set on the WebApp and not the slot + groupIds: [ + privateEndpoint.?service ?? 'sites-${slot.name}' // The required syntax to create the private endpoint for a specific slot + ] + } + } ] - } - } - ] : null - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(app.id, '/'))}-${privateEndpoint.?service ?? 'sites-${slot.name}'}-${index}' - properties: { - privateLinkServiceId: app.id // Must be set on the WebApp and not the slot - groupIds: [ - privateEndpoint.?service ?? 'sites-${slot.name}' // The required syntax to create the private endpoint for a specific slot + : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(app.id, '/'))}-${privateEndpoint.?service ?? 'sites-${slot.name}'}-${index}' + properties: { + privateLinkServiceId: app.id // Must be set on the WebApp and not the slot + groupIds: [ + privateEndpoint.?service ?? 'sites-${slot.name}' // The required syntax to create the private endpoint for a specific slot + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] +] @description('The name of the slot.') output name string = slot.name diff --git a/avm/res/web/site/tests/e2e/functionApp.defaults/dependencies.bicep b/avm/res/web/site/tests/e2e/functionApp.defaults/dependencies.bicep index cd93e7ed3f..dd34e10b1c 100644 --- a/avm/res/web/site/tests/e2e/functionApp.defaults/dependencies.bicep +++ b/avm/res/web/site/tests/e2e/functionApp.defaults/dependencies.bicep @@ -5,16 +5,16 @@ param location string = resourceGroup().location param serverFarmName string resource serverFarm 'Microsoft.Web/serverfarms@2022-03-01' = { - name: serverFarmName - location: location - sku: { - name: 'S1' - tier: 'Standard' - size: 'S1' - family: 'S' - capacity: 1 - } - properties: {} + name: serverFarmName + location: location + sku: { + name: 'S1' + tier: 'Standard' + size: 'S1' + family: 'S' + capacity: 1 + } + properties: {} } @description('The resource ID of the created Server Farm.') diff --git a/avm/res/web/site/tests/e2e/functionApp.defaults/main.test.bicep b/avm/res/web/site/tests/e2e/functionApp.defaults/main.test.bicep index a9d3e90e3a..49f241e3f0 100644 --- a/avm/res/web/site/tests/e2e/functionApp.defaults/main.test.bicep +++ b/avm/res/web/site/tests/e2e/functionApp.defaults/main.test.bicep @@ -45,19 +45,21 @@ 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 - kind: 'functionapp' - serverFarmResourceId: nestedDependencies.outputs.serverFarmResourceId - siteConfig: { - alwaysOn: true +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 + kind: 'functionapp' + serverFarmResourceId: nestedDependencies.outputs.serverFarmResourceId + siteConfig: { + alwaysOn: true + } } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/web/site/tests/e2e/functionApp.max/main.test.bicep b/avm/res/web/site/tests/e2e/functionApp.max/main.test.bicep index c336ca84ad..4ec82011d0 100644 --- a/avm/res/web/site/tests/e2e/functionApp.max/main.test.bicep +++ b/avm/res/web/site/tests/e2e/functionApp.max/main.test.bicep @@ -65,169 +65,174 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t // ============== // // For the below test case, please consider the guidelines described here: https://github.com/Azure/ResourceModules/wiki/Getting%20started%20-%20Scenario%202%20Onboard%20module%20library%20and%20CI%20environment#microsoftwebsites @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 - kind: 'functionapp' - serverFarmResourceId: nestedDependencies.outputs.serverFarmResourceId - appInsightResourceId: nestedDependencies.outputs.applicationInsightsResourceId - appSettingsKeyValuePairs: { - AzureFunctionsJobHost__logging__logLevel__default: 'Trace' - EASYAUTH_SECRET: 'https://${namePrefix}-KeyVault${environment().suffixes.keyvaultDns}/secrets/Modules-Test-SP-Password' - FUNCTIONS_EXTENSION_VERSION: '~4' - FUNCTIONS_WORKER_RUNTIME: 'dotnet' - } - authSettingV2Configuration: { - globalValidation: { - requireAuthentication: true - unauthenticatedClientAction: 'Return401' +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 + kind: 'functionapp' + serverFarmResourceId: nestedDependencies.outputs.serverFarmResourceId + appInsightResourceId: nestedDependencies.outputs.applicationInsightsResourceId + appSettingsKeyValuePairs: { + AzureFunctionsJobHost__logging__logLevel__default: 'Trace' + EASYAUTH_SECRET: 'https://${namePrefix}-KeyVault${environment().suffixes.keyvaultDns}/secrets/Modules-Test-SP-Password' + FUNCTIONS_EXTENSION_VERSION: '~4' + FUNCTIONS_WORKER_RUNTIME: 'dotnet' } - httpSettings: { - forwardProxy: { - convention: 'NoProxy' - } - requireHttps: true - routes: { - apiPrefix: '/.auth' + authSettingV2Configuration: { + globalValidation: { + requireAuthentication: true + unauthenticatedClientAction: 'Return401' } - } - identityProviders: { - azureActiveDirectory: { - enabled: true - login: { - disableWWWAuthenticate: false + httpSettings: { + forwardProxy: { + convention: 'NoProxy' } - registration: { - clientId: 'd874dd2f-2032-4db1-a053-f0ec243685aa' - clientSecretSettingName: 'EASYAUTH_SECRET' - openIdIssuer: 'https://sts.windows.net/${tenant().tenantId}/v2.0/' + requireHttps: true + routes: { + apiPrefix: '/.auth' } - validation: { - allowedAudiences: [ - 'api://d874dd2f-2032-4db1-a053-f0ec243685aa' - ] - defaultAuthorizationPolicy: { - allowedPrincipals: {} + } + identityProviders: { + azureActiveDirectory: { + enabled: true + login: { + disableWWWAuthenticate: false + } + registration: { + clientId: 'd874dd2f-2032-4db1-a053-f0ec243685aa' + clientSecretSettingName: 'EASYAUTH_SECRET' + openIdIssuer: 'https://sts.windows.net/${tenant().tenantId}/v2.0/' + } + validation: { + allowedAudiences: [ + 'api://d874dd2f-2032-4db1-a053-f0ec243685aa' + ] + defaultAuthorizationPolicy: { + allowedPrincipals: {} + } + jwtClaimChecks: {} } - jwtClaimChecks: {} } } - } - login: { - allowedExternalRedirectUrls: [ - 'string' - ] - cookieExpiration: { - convention: 'FixedTime' - timeToExpiration: '08:00:00' - } - nonce: { - nonceExpirationInterval: '00:05:00' - validateNonce: true + login: { + allowedExternalRedirectUrls: [ + 'string' + ] + cookieExpiration: { + convention: 'FixedTime' + timeToExpiration: '08:00:00' + } + nonce: { + nonceExpirationInterval: '00:05:00' + validateNonce: true + } + preserveUrlFragmentsForLogins: false + routes: {} + tokenStore: { + azureBlobStorage: {} + enabled: true + fileSystem: {} + tokenRefreshExtensionHours: 72 + } } - preserveUrlFragmentsForLogins: false - routes: {} - tokenStore: { - azureBlobStorage: {} + platform: { enabled: true - fileSystem: {} - tokenRefreshExtensionHours: 72 + runtimeVersion: '~1' } } - platform: { - enabled: true - runtimeVersion: '~1' - } - } - basicPublishingCredentialsPolicies: [ - { - name: 'ftp' - allow: false - } - { - name: 'scm' - allow: false + basicPublishingCredentialsPolicies: [ + { + name: 'ftp' + allow: false + } + { + name: 'scm' + allow: false + } + ] + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' + privateEndpoints: [ + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - privateEndpoints: [ - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + } + ] + 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' + } + ] + keyVaultAccessIdentityResourceId: nestedDependencies.outputs.managedIdentityResourceId + siteConfig: { + alwaysOn: true + use32BitWorkerProcess: false } - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId + storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + storageAccountUseIdentityAuthentication: true + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId ] } - ] - 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' - } - ] - keyVaultAccessIdentityResourceId: nestedDependencies.outputs.managedIdentityResourceId - siteConfig: { - alwaysOn: true - use32BitWorkerProcess: false - } - storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId - storageAccountUseIdentityAuthentication: true - managedIdentities: { - systemAssigned: true - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId + hybridConnectionRelays: [ + { + resourceId: nestedDependencies.outputs.hybridConnectionResourceId + sendKeyName: 'defaultSender' + } ] } - hybridConnectionRelays: [ - { - resourceId: nestedDependencies.outputs.hybridConnectionResourceId - sendKeyName: 'defaultSender' - } + dependsOn: [ + nestedDependencies + diagnosticDependencies ] } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/web/site/tests/e2e/waf-aligned/main.test.bicep b/avm/res/web/site/tests/e2e/waf-aligned/main.test.bicep index 118c87cf79..cce9097635 100644 --- a/avm/res/web/site/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/web/site/tests/e2e/waf-aligned/main.test.bicep @@ -58,51 +58,53 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t // 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 - kind: 'app' - serverFarmResourceId: nestedDependencies.outputs.serverFarmResourceId - diagnosticSettings: [ - { - 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 + kind: 'app' + serverFarmResourceId: nestedDependencies.outputs.serverFarmResourceId + diagnosticSettings: [ + { + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + httpsOnly: true + siteConfig: { + healthCheckPath: '/healthz' + alwaysOn: true + metadata: [ + { + name: 'CURRENT_STACK' + value: 'dotnetcore' + } + ] } - ] - httpsOnly: true - siteConfig: { - healthCheckPath: '/healthz' - alwaysOn: true - metadata: [ + basicPublishingCredentialsPolicies: [ + { + name: 'ftp' + allow: false + } { - name: 'CURRENT_STACK' - value: 'dotnetcore' + name: 'scm' + allow: false } ] + scmSiteAlsoStopped: true + vnetContentShareEnabled: true + vnetImagePullEnabled: true + vnetRouteAllEnabled: true + publicNetworkAccess: 'Disabled' } - basicPublishingCredentialsPolicies: [ - { - name: 'ftp' - allow: false - } - { - name: 'scm' - allow: false - } + dependsOn: [ + nestedDependencies + diagnosticDependencies ] - scmSiteAlsoStopped: true - vnetContentShareEnabled: true - vnetImagePullEnabled: true - vnetRouteAllEnabled: true - publicNetworkAccess: 'Disabled' } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/web/site/tests/e2e/webApp.defaults/dependencies.bicep b/avm/res/web/site/tests/e2e/webApp.defaults/dependencies.bicep index cd93e7ed3f..dd34e10b1c 100644 --- a/avm/res/web/site/tests/e2e/webApp.defaults/dependencies.bicep +++ b/avm/res/web/site/tests/e2e/webApp.defaults/dependencies.bicep @@ -5,16 +5,16 @@ param location string = resourceGroup().location param serverFarmName string resource serverFarm 'Microsoft.Web/serverfarms@2022-03-01' = { - name: serverFarmName - location: location - sku: { - name: 'S1' - tier: 'Standard' - size: 'S1' - family: 'S' - capacity: 1 - } - properties: {} + name: serverFarmName + location: location + sku: { + name: 'S1' + tier: 'Standard' + size: 'S1' + family: 'S' + capacity: 1 + } + properties: {} } @description('The resource ID of the created Server Farm.') diff --git a/avm/res/web/site/tests/e2e/webApp.defaults/main.test.bicep b/avm/res/web/site/tests/e2e/webApp.defaults/main.test.bicep index baecb8fbaf..c4b0bce825 100644 --- a/avm/res/web/site/tests/e2e/webApp.defaults/main.test.bicep +++ b/avm/res/web/site/tests/e2e/webApp.defaults/main.test.bicep @@ -45,21 +45,23 @@ 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 - kind: 'app' - serverFarmResourceId: nestedDependencies.outputs.serverFarmResourceId - siteConfig: { - healthCheckPath: '/healthz' - alwaysOn: true +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 + kind: 'app' + serverFarmResourceId: nestedDependencies.outputs.serverFarmResourceId + siteConfig: { + healthCheckPath: '/healthz' + alwaysOn: true + } } + + dependsOn: [ + nestedDependencies + ] } - - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/web/site/tests/e2e/webApp.max/main.test.bicep b/avm/res/web/site/tests/e2e/webApp.max/main.test.bicep index 07b3cf2548..434166b1e2 100644 --- a/avm/res/web/site/tests/e2e/webApp.max/main.test.bicep +++ b/avm/res/web/site/tests/e2e/webApp.max/main.test.bicep @@ -63,196 +63,203 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t // 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 - kind: 'app' - serverFarmResourceId: nestedDependencies.outputs.serverFarmResourceId - 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 + kind: 'app' + serverFarmResourceId: nestedDependencies.outputs.serverFarmResourceId + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + httpsOnly: true + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - httpsOnly: true - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - slots: [ - { - name: 'slot1' - diagnosticSettings: [ - { - name: 'customSetting' - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - privateEndpoints: [ - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + slots: [ + { + name: 'slot1' + diagnosticSettings: [ + { + name: 'customSetting' + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } - service: 'sites-slot1' - } - ] - basicPublishingCredentialsPolicies: [ - { - name: 'ftp' - allow: false - } - { - name: 'scm' - allow: false - } - ] - 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' + ] + privateEndpoints: [ + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + service: 'sites-slot1' + } + ] + basicPublishingCredentialsPolicies: [ + { + name: 'ftp' + allow: false + } + { + name: 'scm' + allow: false + } + ] + 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' + } + ] + siteConfig: { + alwaysOn: true + metadata: [ + { + name: 'CURRENT_STACK' + value: 'dotnetcore' + } + ] } - ] - siteConfig: { - alwaysOn: true - metadata: [ + storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + storageAccountUseIdentityAuthentication: true + hybridConnectionRelays: [ { - name: 'CURRENT_STACK' - value: 'dotnetcore' + resourceId: nestedDependencies.outputs.hybridConnectionResourceId + sendKeyName: 'defaultSender' } ] } - storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId - storageAccountUseIdentityAuthentication: true - hybridConnectionRelays: [ - { - resourceId: nestedDependencies.outputs.hybridConnectionResourceId - sendKeyName: 'defaultSender' - } - ] - } - { - name: 'slot2' - basicPublishingCredentialsPolicies: [ - { - name: 'ftp' + { + name: 'slot2' + basicPublishingCredentialsPolicies: [ + { + name: 'ftp' + } + { + name: 'scm' + } + ] + storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + storageAccountUseIdentityAuthentication: true + } + ] + privateEndpoints: [ + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } + } + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + } + ] + 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' + } + ] + siteConfig: { + alwaysOn: true + metadata: [ { - name: 'scm' + name: 'CURRENT_STACK' + value: 'dotnetcore' } ] - storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId - storageAccountUseIdentityAuthentication: true - } - ] - privateEndpoints: [ - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } } - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId + storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + storageAccountUseIdentityAuthentication: true + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId ] } - ] - 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' - } - ] - siteConfig: { - alwaysOn: true - metadata: [ + basicPublishingCredentialsPolicies: [ + { + name: 'ftp' + allow: false + } { - name: 'CURRENT_STACK' - value: 'dotnetcore' + name: 'scm' + allow: false } ] - } - storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId - storageAccountUseIdentityAuthentication: true - managedIdentities: { - systemAssigned: true - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId + hybridConnectionRelays: [ + { + resourceId: nestedDependencies.outputs.hybridConnectionResourceId + sendKeyName: 'defaultSender' + } ] + scmSiteAlsoStopped: true + vnetContentShareEnabled: true + vnetImagePullEnabled: true + vnetRouteAllEnabled: true + publicNetworkAccess: 'Disabled' } - basicPublishingCredentialsPolicies: [ - { - name: 'ftp' - allow: false - } - { - name: 'scm' - allow: false - } - - ] - hybridConnectionRelays: [ - { - resourceId: nestedDependencies.outputs.hybridConnectionResourceId - sendKeyName: 'defaultSender' - } + dependsOn: [ + nestedDependencies + diagnosticDependencies ] - scmSiteAlsoStopped: true - vnetContentShareEnabled: true - vnetImagePullEnabled: true - vnetRouteAllEnabled: true - publicNetworkAccess: 'Disabled' } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/web/site/tests/e2e/webAppLinux.defaults/dependencies.bicep b/avm/res/web/site/tests/e2e/webAppLinux.defaults/dependencies.bicep index cc8e14c136..25017acf7b 100644 --- a/avm/res/web/site/tests/e2e/webAppLinux.defaults/dependencies.bicep +++ b/avm/res/web/site/tests/e2e/webAppLinux.defaults/dependencies.bicep @@ -5,18 +5,18 @@ param location string = resourceGroup().location param serverFarmName string resource serverFarm 'Microsoft.Web/serverfarms@2022-03-01' = { - name: serverFarmName - location: location - sku: { - name: 'S1' - tier: 'Standard' - size: 'S1' - family: 'S' - capacity: 1 - } - properties: { - reserved: true - } + name: serverFarmName + location: location + sku: { + name: 'S1' + tier: 'Standard' + size: 'S1' + family: 'S' + capacity: 1 + } + properties: { + reserved: true + } } @description('The resource ID of the created Server Farm.') diff --git a/avm/res/web/site/tests/e2e/webAppLinux.defaults/main.test.bicep b/avm/res/web/site/tests/e2e/webAppLinux.defaults/main.test.bicep index 61de2c7c89..d61b339989 100644 --- a/avm/res/web/site/tests/e2e/webAppLinux.defaults/main.test.bicep +++ b/avm/res/web/site/tests/e2e/webAppLinux.defaults/main.test.bicep @@ -45,16 +45,18 @@ 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 - kind: 'app,linux' - serverFarmResourceId: nestedDependencies.outputs.serverFarmResourceId +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 + kind: 'app,linux' + serverFarmResourceId: nestedDependencies.outputs.serverFarmResourceId + } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/web/site/tests/e2e/webAppLinux.max/main.test.bicep b/avm/res/web/site/tests/e2e/webAppLinux.max/main.test.bicep index 41754c557b..ab31f0adb6 100644 --- a/avm/res/web/site/tests/e2e/webAppLinux.max/main.test.bicep +++ b/avm/res/web/site/tests/e2e/webAppLinux.max/main.test.bicep @@ -63,196 +63,203 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t // 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 - kind: 'app,linux' - serverFarmResourceId: nestedDependencies.outputs.serverFarmResourceId - 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 + kind: 'app,linux' + serverFarmResourceId: nestedDependencies.outputs.serverFarmResourceId + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + httpsOnly: true + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - ] - httpsOnly: true - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - slots: [ - { - name: 'slot1' - diagnosticSettings: [ - { - name: 'customSetting' - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - privateEndpoints: [ - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' + slots: [ + { + name: 'slot1' + diagnosticSettings: [ + { + name: 'customSetting' + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId } - service: 'sites-slot1' - } - ] - basicPublishingCredentialsPolicies: [ - { - name: 'ftp' - allow: false - } - { - name: 'scm' - allow: false - } - ] - 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' + ] + privateEndpoints: [ + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + service: 'sites-slot1' + } + ] + basicPublishingCredentialsPolicies: [ + { + name: 'ftp' + allow: false + } + { + name: 'scm' + allow: false + } + ] + 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' + } + ] + siteConfig: { + alwaysOn: true + metadata: [ + { + name: 'CURRENT_STACK' + value: 'dotnetcore' + } + ] } - ] - siteConfig: { - alwaysOn: true - metadata: [ + storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + storageAccountUseIdentityAuthentication: true + hybridConnectionRelays: [ { - name: 'CURRENT_STACK' - value: 'dotnetcore' + resourceId: nestedDependencies.outputs.hybridConnectionResourceId + sendKeyName: 'defaultSender' } ] } - storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId - storageAccountUseIdentityAuthentication: true - hybridConnectionRelays: [ - { - resourceId: nestedDependencies.outputs.hybridConnectionResourceId - sendKeyName: 'defaultSender' - } - ] - } - { - name: 'slot2' - basicPublishingCredentialsPolicies: [ - { - name: 'ftp' + { + name: 'slot2' + basicPublishingCredentialsPolicies: [ + { + name: 'ftp' + } + { + name: 'scm' + } + ] + storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + storageAccountUseIdentityAuthentication: true + } + ] + privateEndpoints: [ + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } + } + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + } + ] + 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' + } + ] + siteConfig: { + alwaysOn: true + metadata: [ { - name: 'scm' + name: 'CURRENT_STACK' + value: 'dotnetcore' } ] - storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId - storageAccountUseIdentityAuthentication: true - } - ] - privateEndpoints: [ - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } } - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId + storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId + storageAccountUseIdentityAuthentication: true + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId ] } - ] - 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' - } - ] - siteConfig: { - alwaysOn: true - metadata: [ + basicPublishingCredentialsPolicies: [ + { + name: 'ftp' + allow: false + } { - name: 'CURRENT_STACK' - value: 'dotnetcore' + name: 'scm' + allow: false } ] - } - storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId - storageAccountUseIdentityAuthentication: true - managedIdentities: { - systemAssigned: true - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId + hybridConnectionRelays: [ + { + resourceId: nestedDependencies.outputs.hybridConnectionResourceId + sendKeyName: 'defaultSender' + } ] + scmSiteAlsoStopped: true + vnetContentShareEnabled: true + vnetImagePullEnabled: true + vnetRouteAllEnabled: true + publicNetworkAccess: 'Disabled' } - basicPublishingCredentialsPolicies: [ - { - name: 'ftp' - allow: false - } - { - name: 'scm' - allow: false - } - - ] - hybridConnectionRelays: [ - { - resourceId: nestedDependencies.outputs.hybridConnectionResourceId - sendKeyName: 'defaultSender' - } + dependsOn: [ + nestedDependencies + diagnosticDependencies ] - scmSiteAlsoStopped: true - vnetContentShareEnabled: true - vnetImagePullEnabled: true - vnetRouteAllEnabled: true - publicNetworkAccess: 'Disabled' } - dependsOn: [ - nestedDependencies - diagnosticDependencies - ] -}] +] diff --git a/avm/res/web/static-site/config/main.json b/avm/res/web/static-site/config/main.json index 63676de877..9e22c932e8 100644 --- a/avm/res/web/static-site/config/main.json +++ b/avm/res/web/static-site/config/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17053065769415076723" + "version": "0.26.54.24096", + "templateHash": "4029344815380998105" }, "name": "Static Web App Site Config", "description": "This module deploys a Static Web App Site Config.", diff --git a/avm/res/web/static-site/custom-domain/main.json b/avm/res/web/static-site/custom-domain/main.json index c208b7bc10..c2215009ab 100644 --- a/avm/res/web/static-site/custom-domain/main.json +++ b/avm/res/web/static-site/custom-domain/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3581008276102913900" + "version": "0.26.54.24096", + "templateHash": "9170296310450777701" }, "name": "Static Web App Site Custom Domains", "description": "This module deploys a Static Web App Site Custom Domain.", diff --git a/avm/res/web/static-site/linked-backend/main.json b/avm/res/web/static-site/linked-backend/main.json index 6a5aba4615..5a49c3bbe7 100644 --- a/avm/res/web/static-site/linked-backend/main.json +++ b/avm/res/web/static-site/linked-backend/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3673239578041396478" + "version": "0.26.54.24096", + "templateHash": "15307923419105312167" }, "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.", diff --git a/avm/res/web/static-site/main.bicep b/avm/res/web/static-site/main.bicep index 92bb14bee0..9ba884ce25 100644 --- a/avm/res/web/static-site/main.bicep +++ b/avm/res/web/static-site/main.bicep @@ -85,40 +85,61 @@ param functionAppSettings object = {} @description('Optional. The custom domains associated with this static site. The deployment will fail as long as the validation records are not present.') param customDomains array = [] -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 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 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') - 'Web Plan Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b') - 'Website Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772') + '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' + ) + 'Web Plan Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b' + ) + 'Website Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'de139f84-1756-47ae-9be6-808fbbe84772' + ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.web-staticSite.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.res.web-staticSite.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} resource staticSite 'Microsoft.Web/staticSites@2021-03-01' = { name: name @@ -142,106 +163,132 @@ resource staticSite 'Microsoft.Web/staticSites@2021-03-01' = { } } -module staticSite_linkedBackend 'linked-backend/main.bicep' = if (!empty(linkedBackend)) { - name: '${uniqueString(deployment().name, location)}-StaticSite-UserDefinedFunction' - params: { - staticSiteName: staticSite.name - backendResourceId: linkedBackend.resourceId - region: contains(linkedBackend, 'location') ? linkedBackend.location : location +module staticSite_linkedBackend 'linked-backend/main.bicep' = + if (!empty(linkedBackend)) { + name: '${uniqueString(deployment().name, location)}-StaticSite-UserDefinedFunction' + params: { + staticSiteName: staticSite.name + backendResourceId: linkedBackend.resourceId + region: contains(linkedBackend, 'location') ? linkedBackend.location : location + } } -} -module staticSite_appSettings 'config/main.bicep' = if (!empty(appSettings)) { - name: '${uniqueString(deployment().name, location)}-StaticSite-appSettings' - params: { - kind: 'appsettings' - staticSiteName: staticSite.name - properties: appSettings +module staticSite_appSettings 'config/main.bicep' = + if (!empty(appSettings)) { + name: '${uniqueString(deployment().name, location)}-StaticSite-appSettings' + params: { + kind: 'appsettings' + staticSiteName: staticSite.name + properties: appSettings + } } -} -module staticSite_functionAppSettings 'config/main.bicep' = if (!empty(functionAppSettings)) { - name: '${uniqueString(deployment().name, location)}-StaticSite-functionAppSettings' - params: { - kind: 'functionappsettings' - staticSiteName: staticSite.name - properties: functionAppSettings +module staticSite_functionAppSettings 'config/main.bicep' = + if (!empty(functionAppSettings)) { + name: '${uniqueString(deployment().name, location)}-StaticSite-functionAppSettings' + params: { + kind: 'functionappsettings' + staticSiteName: staticSite.name + properties: functionAppSettings + } } -} -module staticSite_customDomains 'custom-domain/main.bicep' = [for (customDomain, index) in customDomains: { - name: '${uniqueString(deployment().name, location)}-StaticSite-customDomains-${index}' - params: { - name: customDomain - staticSiteName: staticSite.name - validationMethod: indexOf(customDomain, '.') == lastIndexOf(customDomain, '.') ? 'dns-txt-token' : 'cname-delegation' +module staticSite_customDomains 'custom-domain/main.bicep' = [ + for (customDomain, index) in customDomains: { + name: '${uniqueString(deployment().name, location)}-StaticSite-customDomains-${index}' + params: { + name: customDomain + staticSiteName: staticSite.name + validationMethod: indexOf(customDomain, '.') == lastIndexOf(customDomain, '.') + ? 'dns-txt-token' + : 'cname-delegation' + } } -}] +] -resource staticSite_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.' +resource staticSite_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: staticSite } - scope: staticSite -} -resource staticSite_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(staticSite.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - 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 +resource staticSite_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(staticSite.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + 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: staticSite } - scope: staticSite -}] - -module staticSite_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-StaticSite-PrivateEndpoint-${index}' - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(staticSite.id, '/'))}-${privateEndpoint.?service ?? 'staticSites'}-${index}' - privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(staticSite.id, '/'))}-${privateEndpoint.?service ?? 'staticSites'}-${index}' - properties: { - privateLinkServiceId: staticSite.id - groupIds: [ - privateEndpoint.?service ?? 'staticSites' +] + +module staticSite_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-StaticSite-PrivateEndpoint-${index}' + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(staticSite.id, '/'))}-${privateEndpoint.?service ?? 'staticSites'}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(staticSite.id, '/'))}-${privateEndpoint.?service ?? 'staticSites'}-${index}' + properties: { + privateLinkServiceId: staticSite.id + groupIds: [ + privateEndpoint.?service ?? 'staticSites' + ] + } + } ] - } - } - ] : null - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(staticSite.id, '/'))}-${privateEndpoint.?service ?? 'staticSites'}-${index}' - properties: { - privateLinkServiceId: staticSite.id - groupIds: [ - privateEndpoint.?service ?? 'staticSites' + : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(staticSite.id, '/'))}-${privateEndpoint.?service ?? 'staticSites'}-${index}' + properties: { + privateLinkServiceId: staticSite.id + groupIds: [ + privateEndpoint.?service ?? 'staticSites' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry - location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName - privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } } -}] +] @description('The name of the static site.') output name string = staticSite.name diff --git a/avm/res/web/static-site/main.json b/avm/res/web/static-site/main.json index 6d473d52c2..49bae2b6a6 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.25.53.49325", - "templateHash": "18245734514085730321" + "version": "0.26.54.24096", + "templateHash": "7529430437285380768" }, "name": "Static Web Apps", "description": "This module deploys a Static Web App.", @@ -596,8 +596,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3673239578041396478" + "version": "0.26.54.24096", + "templateHash": "15307923419105312167" }, "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.", @@ -698,8 +698,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17053065769415076723" + "version": "0.26.54.24096", + "templateHash": "4029344815380998105" }, "name": "Static Web App Site Config", "description": "This module deploys a Static Web App Site Config.", @@ -793,8 +793,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "17053065769415076723" + "version": "0.26.54.24096", + "templateHash": "4029344815380998105" }, "name": "Static Web App Site Config", "description": "This module deploys a Static Web App Site Config.", @@ -889,8 +889,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "3581008276102913900" + "version": "0.26.54.24096", + "templateHash": "9170296310450777701" }, "name": "Static Web App Site Custom Domains", "description": "This module deploys a Static Web App Site Custom Domain.", diff --git a/avm/res/web/static-site/tests/e2e/defaults/main.test.bicep b/avm/res/web/static-site/tests/e2e/defaults/main.test.bicep index 750c86d508..255a33dba4 100644 --- a/avm/res/web/static-site/tests/e2e/defaults/main.test.bicep +++ b/avm/res/web/static-site/tests/e2e/defaults/main.test.bicep @@ -36,11 +36,13 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @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 +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 + } } -}] +] diff --git a/avm/res/web/static-site/tests/e2e/max/main.test.bicep b/avm/res/web/static-site/tests/e2e/max/main.test.bicep index 4db79418e9..45de7cf720 100644 --- a/avm/res/web/static-site/tests/e2e/max/main.test.bicep +++ b/avm/res/web/static-site/tests/e2e/max/main.test.bicep @@ -48,80 +48,85 @@ 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' - allowConfigFileUpdates: true - enterpriseGradeCdnStatus: 'Disabled' - location: resourceLocation - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - privateEndpoints: [ - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + allowConfigFileUpdates: true + enterpriseGradeCdnStatus: 'Disabled' + location: resourceLocation + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId + privateEndpoints: [ + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + } + ] + 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' + } + ] + sku: 'Standard' + stagingEnvironmentPolicy: 'Enabled' + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId ] } - ] - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + appSettings: { + foo: 'bar' + setting: 1 } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + functionAppSettings: { + foo: 'bar' + setting: 1 } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' + linkedBackend: { + resourceId: nestedDependencies.outputs.siteResourceId + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - sku: 'Standard' - stagingEnvironmentPolicy: 'Enabled' - managedIdentities: { - systemAssigned: true - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - appSettings: { - foo: 'bar' - setting: 1 - } - functionAppSettings: { - foo: 'bar' - setting: 1 - } - linkedBackend: { - resourceId: nestedDependencies.outputs.siteResourceId - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/res/web/static-site/tests/e2e/waf-aligned/main.test.bicep b/avm/res/web/static-site/tests/e2e/waf-aligned/main.test.bicep index e95bd5db2b..77c04b71b2 100644 --- a/avm/res/web/static-site/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/web/static-site/tests/e2e/waf-aligned/main.test.bicep @@ -47,51 +47,53 @@ 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' - allowConfigFileUpdates: true - enterpriseGradeCdnStatus: 'Disabled' - location: resourceLocation - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - privateEndpoints: [ - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + allowConfigFileUpdates: true + enterpriseGradeCdnStatus: 'Disabled' + location: resourceLocation + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + privateEndpoints: [ + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } + ] + sku: 'Standard' + stagingEnvironmentPolicy: 'Enabled' + appSettings: { + foo: 'bar' + setting: 1 + } + functionAppSettings: { + foo: 'bar' + setting: 1 + } + linkedBackend: { + resourceId: nestedDependencies.outputs.siteResourceId + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } - ] - sku: 'Standard' - stagingEnvironmentPolicy: 'Enabled' - appSettings: { - foo: 'bar' - setting: 1 - } - functionAppSettings: { - foo: 'bar' - setting: 1 - } - linkedBackend: { - resourceId: nestedDependencies.outputs.siteResourceId - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' } + dependsOn: [ + nestedDependencies + ] } - dependsOn: [ - nestedDependencies - ] -}] +] diff --git a/avm/utilities/tools/helper/src/src.main.bicep b/avm/utilities/tools/helper/src/src.main.bicep index 88066209d3..7d14192161 100644 --- a/avm/utilities/tools/helper/src/src.main.bicep +++ b/avm/utilities/tools/helper/src/src.main.bicep @@ -19,23 +19,24 @@ param enableTelemetry bool = true // Resources // // ============== // -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.[[REPLACE WITH TELEMETRY IDENTIFIER]].${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = + if (enableTelemetry) { + name: '46d3xbcp.[[REPLACE WITH TELEMETRY IDENTIFIER]].${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } } } } } -} // // Add your resources here diff --git a/avm/utilities/tools/helper/src/src.main.test.bicep b/avm/utilities/tools/helper/src/src.main.test.bicep index 4bcc560ab0..0e8b537041 100644 --- a/avm/utilities/tools/helper/src/src.main.test.bicep +++ b/avm/utilities/tools/helper/src/src.main.test.bicep @@ -35,12 +35,14 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - // You parameters go here - name: '${namePrefix}${serviceShort}001' - location: resourceLocation +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + // You parameters go here + name: '${namePrefix}${serviceShort}001' + location: resourceLocation + } } -}] +] From 106ea7fcd0d2fe247cc2516108e88a59e7dc093f Mon Sep 17 00:00:00 2001 From: Kris Baranek Date: Wed, 27 Mar 2024 10:25:42 +0100 Subject: [PATCH 71/73] fix: Fixing the `expirationTime` issue in `avm/res/desktop-virtualization/scaling-plan` (#1413) ## Description Module: `avm/res/desktop-virtualization/scaling-plan` The pipeline of this module failed because of a hardcoded parameter `expirationTime` in the `dependencies.bicep`. This parameter must be set to a date between one hour and 30 day from the time of the deployment. The hardcoded value worked for some time and then (after 30 days) stopped working. With this PR, the `expirationTime` will be calculated dynamically based on the current time and will be set to 'current time + 32 days' Fixes #1382 Fixes #1081 ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.desktop-virtualization.scaling-plan](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.desktop-virtualization.scaling-plan.yml/badge.svg?branch=users%2Fkrbar%2FscalingPlanFix)](https://github.com/krbar/bicep-registry-modules/actions/workflows/avm.res.desktop-virtualization.scaling-plan.yml) | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [x] Azure Verified Module updates: - [x] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [x] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [x] I have run `Set-AVMModule` locally to generate the supporting module files. - [x] My corresponding pipelines / checks run clean and green without any errors or warnings --- .../scaling-plan/tests/e2e/max/dependencies.bicep | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/avm/res/desktop-virtualization/scaling-plan/tests/e2e/max/dependencies.bicep b/avm/res/desktop-virtualization/scaling-plan/tests/e2e/max/dependencies.bicep index 97b98541d9..7b804fb6e7 100644 --- a/avm/res/desktop-virtualization/scaling-plan/tests/e2e/max/dependencies.bicep +++ b/avm/res/desktop-virtualization/scaling-plan/tests/e2e/max/dependencies.bicep @@ -6,6 +6,9 @@ param tags object = {} @description('Required. The name of the Managed Identity to create.') param managedIdentityName string +@description('Optional. Expiration time of Host Pool registration token. Should be between one hour and 30 days from now and the format is like \'2023-12-24T12:00:00.0000000Z\'. If not provided, the expiration time will be set to two days from now.') +param expirationTime string = dateTimeAdd(utcNow(), 'P2D') + resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { name: managedIdentityName location: location @@ -27,7 +30,7 @@ resource hostPool 'Microsoft.DesktopVirtualization/hostPools@2022-09-09' = { startVMOnConnect: false validationEnvironment: false registrationInfo: { - expirationTime: '2024-02-24T12:00:00.0000000Z' + expirationTime: expirationTime token: null registrationTokenOperation: 'Update' } From 54fdcb336492c6cc49a1b339b0540c432acc9d53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20H=C3=A9zser?= Date: Wed, 27 Mar 2024 10:27:32 +0100 Subject: [PATCH 72/73] feat: Updates base image and adds features the nice way, allows local testing (#1406) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description Updates devcontainer - base image - installs features via "features" - allows local GitHub action testing ## Pipeline Reference not needed ## Type of Change - [x] Update to CI Environment or utilities (Non-module effecting changes) - [ ] Azure Verified Module updates: - [ ] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [ ] I have run `Set-AVMModule` locally to generate the supporting module files. - [ ] My corresponding pipelines / checks run clean and green without any errors or warnings --------- Co-authored-by: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Co-authored-by: Sebastian Gräf --- .devcontainer/devcontainer.json | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 5a6abd02d4..853cd7c506 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,6 +1,6 @@ { "name": "Ubuntu", - "image": "mcr.microsoft.com/devcontainers/javascript-node:0-18-bullseye", + "image": "mcr.microsoft.com/devcontainers/javascript-node:20-bullseye", "customizations": { "vscode": { "extensions": [ @@ -17,15 +17,26 @@ ] } }, - "postCreateCommand": "npm install -g prettier && dotnet tool install -g Azure.Bicep.RegistryModuleTool && pwsh -C Install-Module Az.Accounts -Repository PSGallery -Force && pwsh -C Install-Module Az.Resources -Repository PSGallery -Force && pwsh -C Install-Module Az.KeyVault -Repository PSGallery -Force", - "postStartCommand": "az bicep install", + "postCreateCommand": "dotnet tool install -g Azure.Bicep.RegistryModuleTool", + "postStartCommand": "", "remoteEnv": { "PATH": "${containerEnv:PATH}:/home/node/.dotnet/tools:/home/node/.azure/bin" }, "features": { - "azure-cli": "latest", - "dotnet": "8.0", + "ghcr.io/devcontainers/features/azure-cli:1": { + "version": "latest", + "installBicep": true + }, + "ghcr.io/devcontainers/features/dotnet:2": {}, "ghcr.io/devcontainers/features/node:1": {}, - "ghcr.io/devcontainers/features/powershell:1": {} + "ghcr.io/devcontainers/features/powershell:1": { + "modules": ["Az.Accounts", "Az.Resources", "Az.KeyVault", "Pester"] + }, + "ghcr.io/devcontainers-contrib/features/prettier:1": {}, + "ghcr.io/devcontainers/features/github-cli:1": {}, + // act to run github actions locally + "ghcr.io/devcontainers-contrib/features/act-asdf:2": {}, + // for act + "ghcr.io/devcontainers/features/docker-outside-of-docker:1": {} } } From 9780289aa14cd87d2afb7c6597e2f64ac025492b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Mar 2024 17:58:28 +0100 Subject: [PATCH 73/73] fix: bump azure/powershell from 1 to 2 (#1441) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [azure/powershell](https://github.com/azure/powershell) from 1 to 2.

Release notes

Sourced from azure/powershell's releases.

Azure PowerShell Action v2

What's Changed

Azure PowerShell Action v1.4.0

  • Supported macOS and self-hosted runners.

Azure PowerShell Action v1.3.0

  • Updated the versions of dependencies.
  • Added an example to run a PowerShell script file.
  • Updated the User Agent of Azure PowerShell Action.

Updated with Node16 and Code scanning workflow for incoming changes

No release notes provided.

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=azure/powershell&package-manager=github_actions&previous-version=1&new-version=2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/avm.platform.check.psrule.yml | 4 ++-- .github/workflows/avm.platform.publish-tag.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/avm.platform.check.psrule.yml b/.github/workflows/avm.platform.check.psrule.yml index fd7a7d9308..6a61e8bacd 100644 --- a/.github/workflows/avm.platform.check.psrule.yml +++ b/.github/workflows/avm.platform.check.psrule.yml @@ -74,7 +74,7 @@ jobs: # [Token replacement] task(s) # --------------------------- - name: Replace tokens in relevant files - uses: azure/powershell@v1 + uses: azure/powershell@v2 with: azPSVersion: "latest" inlineScript: | @@ -155,7 +155,7 @@ jobs: #----------------------------- - name: Parse CSV content if: always() - uses: azure/powershell@v1 + uses: azure/powershell@v2 with: azPSVersion: "latest" inlineScript: | diff --git a/.github/workflows/avm.platform.publish-tag.yml b/.github/workflows/avm.platform.publish-tag.yml index 3f1488ebd3..c8dd150deb 100644 --- a/.github/workflows/avm.platform.publish-tag.yml +++ b/.github/workflows/avm.platform.publish-tag.yml @@ -44,7 +44,7 @@ jobs: - name: "Publish tagged module to public bicep registry" id: publish_tag - uses: azure/powershell@v1 + uses: azure/powershell@v2 with: azPSVersion: "latest" inlineScript: | @@ -71,7 +71,7 @@ jobs: Write-Output '::endgroup::' - name: "Validate publish" - uses: azure/powershell@v1 + uses: azure/powershell@v2 if: ${{ steps.publish_tag.outputs.version != '' && steps.publish_tag.outputs.publishedModuleName != '' }} with: azPSVersion: "latest"