From 7ecd1a5c7b663a7f8ede842b668b9b183e44dec2 Mon Sep 17 00:00:00 2001 From: Chris Sidebotham Date: Thu, 12 Oct 2023 14:59:57 +0100 Subject: [PATCH 01/29] adding deployment files --- .../avm.res.network.public-ip-address.yml | 81 +++++++++++++++++++ .../avm.res.network.ssh-public-key.yml | 81 +++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 .github/workflows/avm.res.network.public-ip-address.yml create mode 100644 .github/workflows/avm.res.network.ssh-public-key.yml diff --git a/.github/workflows/avm.res.network.public-ip-address.yml b/.github/workflows/avm.res.network.public-ip-address.yml new file mode 100644 index 0000000000..51e2dc0f6d --- /dev/null +++ b/.github/workflows/avm.res.network.public-ip-address.yml @@ -0,0 +1,81 @@ +name: "avm.res.network.public-ip-address" + +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.public-ip-address.yml" + - "avm/res/network/public-ip-address/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/network/public-ip-address" + workflowPath: ".github/workflows/avm.res.network.public-ip-address.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-20.04 + 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 parameter 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 }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Module" + 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 }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit diff --git a/.github/workflows/avm.res.network.ssh-public-key.yml b/.github/workflows/avm.res.network.ssh-public-key.yml new file mode 100644 index 0000000000..24075037bd --- /dev/null +++ b/.github/workflows/avm.res.network.ssh-public-key.yml @@ -0,0 +1,81 @@ +name: "avm.res.network.ssh-public-key" + +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.ssh-public-key.yml" + - "avm/res/network/ssh-public-key/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/network/ssh-public-key" + workflowPath: ".github/workflows/avm.res.network.ssh-public-key.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-20.04 + 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 parameter 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 }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Module" + 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 }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit From 0f15c86fac29199f4fb3fc05e12025d93a3cee83 Mon Sep 17 00:00:00 2001 From: Chris Sidebotham Date: Thu, 12 Oct 2023 15:03:51 +0100 Subject: [PATCH 02/29] ficing rp ref --- ...blic-key.yml => avm.res.compute.ssh-public-key.yml} | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename .github/workflows/{avm.res.network.ssh-public-key.yml => avm.res.compute.ssh-public-key.yml} (89%) diff --git a/.github/workflows/avm.res.network.ssh-public-key.yml b/.github/workflows/avm.res.compute.ssh-public-key.yml similarity index 89% rename from .github/workflows/avm.res.network.ssh-public-key.yml rename to .github/workflows/avm.res.compute.ssh-public-key.yml index 24075037bd..f0c1fdd5d5 100644 --- a/.github/workflows/avm.res.network.ssh-public-key.yml +++ b/.github/workflows/avm.res.compute.ssh-public-key.yml @@ -1,4 +1,4 @@ -name: "avm.res.network.ssh-public-key" +name: "avm.res.compute.ssh-public-key" on: schedule: @@ -27,14 +27,14 @@ on: paths: - ".github/actions/templates/avm-**" - ".github/workflows/avm.template.module.yml" - - ".github/workflows/avm.res.network.ssh-public-key.yml" - - "avm/res/network/ssh-public-key/**" + - ".github/workflows/avm.res.compute.ssh-public-key.yml" + - "avm/res/compute/ssh-public-key/**" - "avm/utilities/pipelines/**" - "!*/**/README.md" env: - modulePath: "avm/res/network/ssh-public-key" - workflowPath: ".github/workflows/avm.res.network.ssh-public-key.yml" + modulePath: "avm/res/compute/ssh-public-key" + workflowPath: ".github/workflows/avm.res.compute.ssh-public-key.yml" concurrency: group: ${{ github.workflow }} From 482add66b892395450c7c89894adfb8e62d64adf Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Tue, 17 Oct 2023 09:55:50 +0100 Subject: [PATCH 03/29] Adding workflow file --- .../workflows/avm.res.network.dnsresolver.yml | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 .github/workflows/avm.res.network.dnsresolver.yml diff --git a/.github/workflows/avm.res.network.dnsresolver.yml b/.github/workflows/avm.res.network.dnsresolver.yml new file mode 100644 index 0000000000..449f7afbf5 --- /dev/null +++ b/.github/workflows/avm.res.network.dnsresolver.yml @@ -0,0 +1,81 @@ +name: "avm.res.network.dnsresolver" + +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.dnsresolver.yml" + - "avm/res/network/dnsresolver/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/network/dnsresolver" + workflowPath: ".github/workflows/avm.res.network.dnsresolver.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-20.04 + 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 parameter 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 }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Module" + 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 }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit From fba537518295b8b3f6611fc50bcaf2c29c2f752f Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Wed, 18 Oct 2023 20:47:21 +0100 Subject: [PATCH 04/29] fixing path --- ...k.dnsresolver.yml => avm.res.network.dns-resolver.yml} | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename .github/workflows/{avm.res.network.dnsresolver.yml => avm.res.network.dns-resolver.yml} (91%) diff --git a/.github/workflows/avm.res.network.dnsresolver.yml b/.github/workflows/avm.res.network.dns-resolver.yml similarity index 91% rename from .github/workflows/avm.res.network.dnsresolver.yml rename to .github/workflows/avm.res.network.dns-resolver.yml index 449f7afbf5..62bbf80dd3 100644 --- a/.github/workflows/avm.res.network.dnsresolver.yml +++ b/.github/workflows/avm.res.network.dns-resolver.yml @@ -27,14 +27,14 @@ on: paths: - ".github/actions/templates/avm-**" - ".github/workflows/avm.template.module.yml" - - ".github/workflows/avm.res.network.dnsresolver.yml" - - "avm/res/network/dnsresolver/**" + - ".github/workflows/avm.res.network.dns-resolver.yml" + - "avm/res/network/dns-resolver/**" - "avm/utilities/pipelines/**" - "!*/**/README.md" env: - modulePath: "avm/res/network/dnsresolver" - workflowPath: ".github/workflows/avm.res.network.dnsresolver.yml" + modulePath: "avm/res/network/dns-resolver" + workflowPath: ".github/workflows/avm.res.network.dns-resolver.yml" concurrency: group: ${{ github.workflow }} From 05152a806c654af35b2bb8f8a40c5bf5b2c97c90 Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Wed, 18 Oct 2023 20:48:12 +0100 Subject: [PATCH 05/29] Fixing Workflow name --- .github/workflows/avm.res.network.dns-resolver.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/avm.res.network.dns-resolver.yml b/.github/workflows/avm.res.network.dns-resolver.yml index 62bbf80dd3..e16affaed8 100644 --- a/.github/workflows/avm.res.network.dns-resolver.yml +++ b/.github/workflows/avm.res.network.dns-resolver.yml @@ -1,4 +1,4 @@ -name: "avm.res.network.dnsresolver" +name: "avm.res.network.dns-resolver" on: schedule: From f8d04c6eb8bce56c409e7bc8c4b050829e786684 Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Thu, 19 Oct 2023 17:35:54 +0100 Subject: [PATCH 06/29] adding workflow --- .../avm.res.network.private-dns-zone.yml | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 .github/workflows/avm.res.network.private-dns-zone.yml diff --git a/.github/workflows/avm.res.network.private-dns-zone.yml b/.github/workflows/avm.res.network.private-dns-zone.yml new file mode 100644 index 0000000000..d2560f4586 --- /dev/null +++ b/.github/workflows/avm.res.network.private-dns-zone.yml @@ -0,0 +1,81 @@ +name: "avm.res.network.private-dns-zone" + +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.private-dns-zone.yml" + - "avm/res/network/private-dns-zone/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/network/private-dns-zone" + workflowPath: ".github/workflows/avm.res.network.private-dns-zone.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-20.04 + 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 parameter 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 }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Module" + 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 }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit From 6993c4d95c3802499beaabafad3882031a384d69 Mon Sep 17 00:00:00 2001 From: Chris Sidebotham Date: Wed, 25 Oct 2023 11:56:37 +0100 Subject: [PATCH 07/29] Adding Workflow file --- ...avm.res.network.dns-forwarding-ruleset.yml | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 .github/workflows/avm.res.network.dns-forwarding-ruleset.yml diff --git a/.github/workflows/avm.res.network.dns-forwarding-ruleset.yml b/.github/workflows/avm.res.network.dns-forwarding-ruleset.yml new file mode 100644 index 0000000000..0466115f8b --- /dev/null +++ b/.github/workflows/avm.res.network.dns-forwarding-ruleset.yml @@ -0,0 +1,81 @@ +name: "avm.res.network.dns-forwarding-ruleset" + +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.dns-forwarding-ruleset.yml" + - "avm/res/network/dns-forwarding-ruleset/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/network/dns-forwarding-ruleset" + workflowPath: ".github/workflows/avm.res.network.dns-forwarding-ruleset.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-20.04 + 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 parameter 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 }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Module" + 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 }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit From cf44304b3d8519dd784a43060ae41efddcb26fd7 Mon Sep 17 00:00:00 2001 From: Chris Sidebotham Date: Fri, 27 Oct 2023 09:33:05 +0100 Subject: [PATCH 08/29] Adding workflow file --- .../workflows/avm.res.network.dns-zone.yml | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 .github/workflows/avm.res.network.dns-zone.yml diff --git a/.github/workflows/avm.res.network.dns-zone.yml b/.github/workflows/avm.res.network.dns-zone.yml new file mode 100644 index 0000000000..7ea7e1a99f --- /dev/null +++ b/.github/workflows/avm.res.network.dns-zone.yml @@ -0,0 +1,81 @@ +name: "avm.res.network.dns-zone" + +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.dns-zone.yml" + - "avm/res/network/dns-zone/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/network/dns-zone" + workflowPath: ".github/workflows/avm.res.network.dns-zone.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-20.04 + 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 parameter 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 }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Module" + 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 }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit From c9b6b4cb71485075b402e3c82a1e557edbc44ea6 Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Wed, 1 Nov 2023 16:37:21 +0000 Subject: [PATCH 09/29] Adding workflow file --- .../avm.res.power-bi-dedicated.capacity.yml | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 .github/workflows/avm.res.power-bi-dedicated.capacity.yml diff --git a/.github/workflows/avm.res.power-bi-dedicated.capacity.yml b/.github/workflows/avm.res.power-bi-dedicated.capacity.yml new file mode 100644 index 0000000000..ff110ef84b --- /dev/null +++ b/.github/workflows/avm.res.power-bi-dedicated.capacity.yml @@ -0,0 +1,81 @@ +name: "avm.res.power-bi-dedicated.capacity" + +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.power-bi-dedicated.capacity.yml" + - "avm/respower-bi-dedicated/capacity/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/respower-bi-dedicated/capacity" + workflowPath: ".github/workflows/avm.res.power-bi-dedicated.capacity.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-20.04 + 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 parameter 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 }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Module" + 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 }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit From a3d83a428c0b95c7b05eef466058c0f7c1bffb2b Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Fri, 24 Nov 2023 08:29:07 +0000 Subject: [PATCH 10/29] adding workflow --- .../avm.res.network.service-bus.namespace.yml | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 .github/workflows/avm.res.network.service-bus.namespace.yml diff --git a/.github/workflows/avm.res.network.service-bus.namespace.yml b/.github/workflows/avm.res.network.service-bus.namespace.yml new file mode 100644 index 0000000000..0530590287 --- /dev/null +++ b/.github/workflows/avm.res.network.service-bus.namespace.yml @@ -0,0 +1,81 @@ +name: "avm.res.service-bus.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.service-bus.namespace.yml" + - "avm/res/service-bus/namespace/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/service-bus/namespace" + workflowPath: ".github/workflows/avm.res.service-bus.namespace.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-20.04 + 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 parameter 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 }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Module" + 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 }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit From 915d12c7a713c0bd60ea5b23629cd5f70cd488a1 Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Fri, 24 Nov 2023 14:18:05 +0000 Subject: [PATCH 11/29] Fixing workflow name --- ...ervice-bus.namespace.yml => avm.res.service-bus.namespace.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{avm.res.network.service-bus.namespace.yml => avm.res.service-bus.namespace.yml} (100%) diff --git a/.github/workflows/avm.res.network.service-bus.namespace.yml b/.github/workflows/avm.res.service-bus.namespace.yml similarity index 100% rename from .github/workflows/avm.res.network.service-bus.namespace.yml rename to .github/workflows/avm.res.service-bus.namespace.yml From 1c56bb3d0e3d1e4e393c513790ba2db259c3fde3 Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Thu, 30 Nov 2023 17:23:23 +0000 Subject: [PATCH 12/29] update workflow --- .github/workflows/avm.res.service-bus.namespace.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/avm.res.service-bus.namespace.yml b/.github/workflows/avm.res.service-bus.namespace.yml index 0530590287..4411b8f31c 100644 --- a/.github/workflows/avm.res.service-bus.namespace.yml +++ b/.github/workflows/avm.res.service-bus.namespace.yml @@ -64,6 +64,7 @@ jobs: 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 }}" ############################## From fe017c181f7083aa6f2a28ab3a2839c6aba90421 Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Tue, 12 Dec 2023 13:14:21 +0000 Subject: [PATCH 13/29] updating Test Case s location to fix Pipeline --- avm/res/web/serverfarm/README.md | 12 ++++++------ .../serverfarm/tests/e2e/defaults/main.test.bicep | 2 +- avm/res/web/serverfarm/tests/e2e/max/main.test.bicep | 2 +- .../serverfarm/tests/e2e/waf-aligned/main.test.bicep | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/avm/res/web/serverfarm/README.md b/avm/res/web/serverfarm/README.md index 899d0faf72..ace7e08284 100644 --- a/avm/res/web/serverfarm/README.md +++ b/avm/res/web/serverfarm/README.md @@ -54,7 +54,7 @@ module serverfarm 'br/public:avm/res/web/serverfarm:' = { tier: 'Premium' } // Non-required parameters - location: '' + location: 'northeurope' } } ``` @@ -86,7 +86,7 @@ module serverfarm 'br/public:avm/res/web/serverfarm:' = { }, // Non-required parameters "location": { - "value": "" + "value": "northeurope" } } } @@ -133,7 +133,7 @@ module serverfarm 'br/public:avm/res/web/serverfarm:' = { } ] kind: 'App' - location: '' + location: 'northeurope' lock: { kind: 'CanNotDelete' name: 'lock' @@ -212,7 +212,7 @@ module serverfarm 'br/public:avm/res/web/serverfarm:' = { "value": "App" }, "location": { - "value": "" + "value": "northeurope" }, "lock": { "value": { @@ -297,7 +297,7 @@ module serverfarm 'br/public:avm/res/web/serverfarm:' = { } ] kind: 'App' - location: '' + location: 'northeurope' lock: { kind: 'CanNotDelete' name: 'lock' @@ -358,7 +358,7 @@ module serverfarm 'br/public:avm/res/web/serverfarm:' = { "value": "App" }, "location": { - "value": "" + "value": "northeurope" }, "lock": { "value": { 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 267b7bab2b..0dc694f096 100644 --- a/avm/res/web/serverfarm/tests/e2e/defaults/main.test.bicep +++ b/avm/res/web/serverfarm/tests/e2e/defaults/main.test.bicep @@ -41,7 +41,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { name: '${namePrefix}${serviceShort}001' - location: location + location: 'northeurope' sku: { name: 'P1v3' tier: 'Premium' 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 66c31b8d68..c20ef3e5b2 100644 --- a/avm/res/web/serverfarm/tests/e2e/max/main.test.bicep +++ b/avm/res/web/serverfarm/tests/e2e/max/main.test.bicep @@ -62,7 +62,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { name: '${namePrefix}${serviceShort}001' - location: location + location: 'northeurope' sku: { name: 'P1v3' tier: 'Premium' 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 00cad44e81..ed297fc2a5 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 @@ -53,7 +53,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { name: '${namePrefix}${serviceShort}001' - location: location + location: 'northeurope' sku: { name: 'P1v3' tier: 'Premium' From e9b2e806530b3b0bd3c1e30a14550ed2da4dd8d7 Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Tue, 2 Jan 2024 14:20:30 +0000 Subject: [PATCH 14/29] adding workflow --- .github/workflows/avm.res.web.static-site.yml | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 .github/workflows/avm.res.web.static-site.yml diff --git a/.github/workflows/avm.res.web.static-site.yml b/.github/workflows/avm.res.web.static-site.yml new file mode 100644 index 0000000000..f44dc3a4eb --- /dev/null +++ b/.github/workflows/avm.res.web.static-site.yml @@ -0,0 +1,83 @@ +name: "avm.res.web.static-site" + +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.static-site.yml" + - "avm/res/web/serverfarm/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/web/static-site" + workflowPath: ".github/workflows/avm.res.web.static-site.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-20.04 + 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" + needs: + - job_initialize_pipeline + uses: ./.github/workflows/avm.template.module.yml + with: + workflowInput: "${{ needs.job_initialize_pipeline.outputs.workflowInput }}" + moduleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.moduleTestFilePaths }}" + psRuleModuleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.psRuleModuleTestFilePaths }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit From cdfb68d56078db9f7d801724225aff4421246ddb Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Thu, 15 Feb 2024 16:49:25 +0000 Subject: [PATCH 15/29] Adding workflow --- ...s.digital-twins.digital-twins-instance.yml | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 .github/workflows/avm.res.digital-twins.digital-twins-instance.yml 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 From 40614c1f69ac38eddbaff06ad476b0605480095f Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Wed, 28 Feb 2024 17:58:58 +0000 Subject: [PATCH 16/29] Update forwardTo property to null if empty --- avm/res/service-bus/namespace/topic/subscription/main.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avm/res/service-bus/namespace/topic/subscription/main.bicep b/avm/res/service-bus/namespace/topic/subscription/main.bicep index 545a5cd898..d6afd724d8 100644 --- a/avm/res/service-bus/namespace/topic/subscription/main.bicep +++ b/avm/res/service-bus/namespace/topic/subscription/main.bicep @@ -84,7 +84,7 @@ resource subscription 'Microsoft.ServiceBus/namespaces/topics/subscriptions@2021 duplicateDetectionHistoryTimeWindow: duplicateDetectionHistoryTimeWindow enableBatchedOperations: enableBatchedOperations forwardDeadLetteredMessagesTo: forwardDeadLetteredMessagesTo - forwardTo: !empty(forwardTo) ? forwardTo : namespace::topic.name + forwardTo: !empty(forwardTo) ? forwardTo : null isClientAffine: isClientAffine lockDuration: lockDuration maxDeliveryCount: maxDeliveryCount From 4240d6ca41a4aaeb383633f460512aebd4adebfc Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Wed, 28 Feb 2024 18:10:45 +0000 Subject: [PATCH 17/29] Update templateHash values in Service Bus Namespace and Topic --- avm/res/service-bus/namespace/main.json | 8 ++++---- avm/res/service-bus/namespace/topic/main.json | 6 +++--- .../service-bus/namespace/topic/subscription/main.json | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/avm/res/service-bus/namespace/main.json b/avm/res/service-bus/namespace/main.json index eab333df99..e73e6b2663 100644 --- a/avm/res/service-bus/namespace/main.json +++ b/avm/res/service-bus/namespace/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "16905316086455363065" + "templateHash": "14826558446469955414" }, "name": "Service Bus Namespaces", "description": "This module deploys a Service Bus Namespace.", @@ -2527,7 +2527,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "6815063360089408467" + "templateHash": "13105717209289706682" }, "name": "Service Bus Namespace Topic", "description": "This module deploys a Service Bus Namespace Topic.", @@ -3160,7 +3160,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "6473689586849909439" + "templateHash": "10626633836251297018" }, "name": "Service Bus Namespace Topic Subscription", "description": "This module deploys a Service Bus Namespace Topic Subscription.", @@ -3309,7 +3309,7 @@ "duplicateDetectionHistoryTimeWindow": "[parameters('duplicateDetectionHistoryTimeWindow')]", "enableBatchedOperations": "[parameters('enableBatchedOperations')]", "forwardDeadLetteredMessagesTo": "[parameters('forwardDeadLetteredMessagesTo')]", - "forwardTo": "[if(not(empty(parameters('forwardTo'))), parameters('forwardTo'), parameters('topicName'))]", + "forwardTo": "[if(not(empty(parameters('forwardTo'))), parameters('forwardTo'), null())]", "isClientAffine": "[parameters('isClientAffine')]", "lockDuration": "[parameters('lockDuration')]", "maxDeliveryCount": "[parameters('maxDeliveryCount')]", diff --git a/avm/res/service-bus/namespace/topic/main.json b/avm/res/service-bus/namespace/topic/main.json index 9939b450d7..ed97a90dcd 100644 --- a/avm/res/service-bus/namespace/topic/main.json +++ b/avm/res/service-bus/namespace/topic/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "6815063360089408467" + "templateHash": "13105717209289706682" }, "name": "Service Bus Namespace Topic", "description": "This module deploys a Service Bus Namespace Topic.", @@ -639,7 +639,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "6473689586849909439" + "templateHash": "10626633836251297018" }, "name": "Service Bus Namespace Topic Subscription", "description": "This module deploys a Service Bus Namespace Topic Subscription.", @@ -788,7 +788,7 @@ "duplicateDetectionHistoryTimeWindow": "[parameters('duplicateDetectionHistoryTimeWindow')]", "enableBatchedOperations": "[parameters('enableBatchedOperations')]", "forwardDeadLetteredMessagesTo": "[parameters('forwardDeadLetteredMessagesTo')]", - "forwardTo": "[if(not(empty(parameters('forwardTo'))), parameters('forwardTo'), parameters('topicName'))]", + "forwardTo": "[if(not(empty(parameters('forwardTo'))), parameters('forwardTo'), null())]", "isClientAffine": "[parameters('isClientAffine')]", "lockDuration": "[parameters('lockDuration')]", "maxDeliveryCount": "[parameters('maxDeliveryCount')]", diff --git a/avm/res/service-bus/namespace/topic/subscription/main.json b/avm/res/service-bus/namespace/topic/subscription/main.json index 355214dd25..ae24b1d16b 100644 --- a/avm/res/service-bus/namespace/topic/subscription/main.json +++ b/avm/res/service-bus/namespace/topic/subscription/main.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "6473689586849909439" + "templateHash": "10626633836251297018" }, "name": "Service Bus Namespace Topic Subscription", "description": "This module deploys a Service Bus Namespace Topic Subscription.", @@ -154,7 +154,7 @@ "duplicateDetectionHistoryTimeWindow": "[parameters('duplicateDetectionHistoryTimeWindow')]", "enableBatchedOperations": "[parameters('enableBatchedOperations')]", "forwardDeadLetteredMessagesTo": "[parameters('forwardDeadLetteredMessagesTo')]", - "forwardTo": "[if(not(empty(parameters('forwardTo'))), parameters('forwardTo'), parameters('topicName'))]", + "forwardTo": "[if(not(empty(parameters('forwardTo'))), parameters('forwardTo'), null())]", "isClientAffine": "[parameters('isClientAffine')]", "lockDuration": "[parameters('lockDuration')]", "maxDeliveryCount": "[parameters('maxDeliveryCount')]", From bb507f953f2ea724cdc31cf08fcc001aad14108a Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Tue, 13 Aug 2024 13:54:57 +0200 Subject: [PATCH 18/29] #2578 --- avm/res/key-vault/vault/main.bicep | 12 ++++++------ avm/res/key-vault/vault/main.json | 14 +++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/avm/res/key-vault/vault/main.bicep b/avm/res/key-vault/vault/main.bicep index 3ae40ee117..78c57ce23e 100644 --- a/avm/res/key-vault/vault/main.bicep +++ b/avm/res/key-vault/vault/main.bicep @@ -270,9 +270,9 @@ module keyVault_secrets 'secret/main.bicep' = [ name: secret.name value: secret.value keyVaultName: keyVault.name - attributesEnabled: secret.?attributesEnabled - attributesExp: secret.?attributesExp - attributesNbf: secret.?attributesNbf + attributesEnabled: secret.?atrributes.?enabled + attributesExp: secret.?atrributes.?exp + attributesNbf: secret.?atrributes.?nbf contentType: secret.?contentType tags: secret.?tags ?? tags roleAssignments: secret.?roleAssignments @@ -286,9 +286,9 @@ module keyVault_keys 'key/main.bicep' = [ params: { name: key.name keyVaultName: keyVault.name - attributesEnabled: key.?attributesEnabled - attributesExp: key.?attributesExp - attributesNbf: key.?attributesNbf + attributesEnabled: key.?attributes.?enab + attributesExp: key.?atrributes.?exp + attributesNbf: key.?atrributes.?nbf curveName: (key.?kty != 'RSA' && key.?kty != 'RSA-HSM') ? (key.?curveName ?? 'P-256') : null keyOps: key.?keyOps keySize: (key.?kty == 'RSA' || key.?kty == 'RSA-HSM') ? (key.?keySize ?? 4096) : null diff --git a/avm/res/key-vault/vault/main.json b/avm/res/key-vault/vault/main.json index 770f5100f3..f8fc25f5b2 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.29.47.4906", - "templateHash": "17375579299346578014" + "templateHash": "5007662804339002384" }, "name": "Key Vaults", "description": "This module deploys a Key Vault.", @@ -1445,13 +1445,13 @@ "value": "[parameters('name')]" }, "attributesEnabled": { - "value": "[tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'attributesEnabled')]" + "value": "[tryGet(tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'atrributes'), 'enabled')]" }, "attributesExp": { - "value": "[tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'attributesExp')]" + "value": "[tryGet(tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'atrributes'), 'exp')]" }, "attributesNbf": { - "value": "[tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'attributesNbf')]" + "value": "[tryGet(tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'atrributes'), 'nbf')]" }, "contentType": { "value": "[tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'contentType')]" @@ -1732,13 +1732,13 @@ "value": "[parameters('name')]" }, "attributesEnabled": { - "value": "[tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'attributesEnabled')]" + "value": "[tryGet(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'attributes'), 'enab')]" }, "attributesExp": { - "value": "[tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'attributesExp')]" + "value": "[tryGet(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'atrributes'), 'exp')]" }, "attributesNbf": { - "value": "[tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'attributesNbf')]" + "value": "[tryGet(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'atrributes'), 'nbf')]" }, "curveName": "[if(and(not(equals(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'kty'), 'RSA')), not(equals(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'kty'), 'RSA-HSM'))), createObject('value', coalesce(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'curveName'), 'P-256')), createObject('value', null()))]", "keyOps": { From 7ec58b04847c858dc65dc1ab1cb6d47635df6f16 Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Tue, 13 Aug 2024 15:09:50 +0200 Subject: [PATCH 19/29] typo --- avm/res/key-vault/vault/main.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avm/res/key-vault/vault/main.bicep b/avm/res/key-vault/vault/main.bicep index 78c57ce23e..ac256b2d2d 100644 --- a/avm/res/key-vault/vault/main.bicep +++ b/avm/res/key-vault/vault/main.bicep @@ -286,7 +286,7 @@ module keyVault_keys 'key/main.bicep' = [ params: { name: key.name keyVaultName: keyVault.name - attributesEnabled: key.?attributes.?enab + attributesEnabled: key.?attributes.?enabled attributesExp: key.?atrributes.?exp attributesNbf: key.?atrributes.?nbf curveName: (key.?kty != 'RSA' && key.?kty != 'RSA-HSM') ? (key.?curveName ?? 'P-256') : null From 88d09f18b4501f24d636092c53c289664bb2539a Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Tue, 13 Aug 2024 15:12:58 +0200 Subject: [PATCH 20/29] typo --- avm/res/key-vault/vault/main.bicep | 10 +++++----- avm/res/key-vault/vault/main.json | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/avm/res/key-vault/vault/main.bicep b/avm/res/key-vault/vault/main.bicep index ac256b2d2d..4e6ab84d43 100644 --- a/avm/res/key-vault/vault/main.bicep +++ b/avm/res/key-vault/vault/main.bicep @@ -270,9 +270,9 @@ module keyVault_secrets 'secret/main.bicep' = [ name: secret.name value: secret.value keyVaultName: keyVault.name - attributesEnabled: secret.?atrributes.?enabled - attributesExp: secret.?atrributes.?exp - attributesNbf: secret.?atrributes.?nbf + attributesEnabled: secret.?attributes.?enabled + attributesExp: secret.?attributes.?exp + attributesNbf: secret.?attributes.?nbf contentType: secret.?contentType tags: secret.?tags ?? tags roleAssignments: secret.?roleAssignments @@ -287,8 +287,8 @@ module keyVault_keys 'key/main.bicep' = [ name: key.name keyVaultName: keyVault.name attributesEnabled: key.?attributes.?enabled - attributesExp: key.?atrributes.?exp - attributesNbf: key.?atrributes.?nbf + attributesExp: key.?attributes.?exp + attributesNbf: key.?attributes.?nbf curveName: (key.?kty != 'RSA' && key.?kty != 'RSA-HSM') ? (key.?curveName ?? 'P-256') : null keyOps: key.?keyOps keySize: (key.?kty == 'RSA' || key.?kty == 'RSA-HSM') ? (key.?keySize ?? 4096) : null diff --git a/avm/res/key-vault/vault/main.json b/avm/res/key-vault/vault/main.json index f8fc25f5b2..cdcd99757f 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.29.47.4906", - "templateHash": "5007662804339002384" + "templateHash": "4127506616814902143" }, "name": "Key Vaults", "description": "This module deploys a Key Vault.", @@ -1445,13 +1445,13 @@ "value": "[parameters('name')]" }, "attributesEnabled": { - "value": "[tryGet(tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'atrributes'), 'enabled')]" + "value": "[tryGet(tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'attributes'), 'enabled')]" }, "attributesExp": { - "value": "[tryGet(tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'atrributes'), 'exp')]" + "value": "[tryGet(tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'attributes'), 'exp')]" }, "attributesNbf": { - "value": "[tryGet(tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'atrributes'), 'nbf')]" + "value": "[tryGet(tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'attributes'), 'nbf')]" }, "contentType": { "value": "[tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'contentType')]" @@ -1732,13 +1732,13 @@ "value": "[parameters('name')]" }, "attributesEnabled": { - "value": "[tryGet(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'attributes'), 'enab')]" + "value": "[tryGet(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'attributes'), 'enabled')]" }, "attributesExp": { - "value": "[tryGet(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'atrributes'), 'exp')]" + "value": "[tryGet(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'attributes'), 'exp')]" }, "attributesNbf": { - "value": "[tryGet(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'atrributes'), 'nbf')]" + "value": "[tryGet(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'attributes'), 'nbf')]" }, "curveName": "[if(and(not(equals(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'kty'), 'RSA')), not(equals(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'kty'), 'RSA-HSM'))), createObject('value', coalesce(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'curveName'), 'P-256')), createObject('value', null()))]", "keyOps": { From ff6facc0742b088e3c2384654b501837fc4e0953 Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Fri, 6 Sep 2024 11:10:23 +0100 Subject: [PATCH 21/29] Adding logic to skip for non resource modules --- .../Get-AvailableResourceLocation.ps1 | 69 +++++++++++-------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/avm/utilities/pipelines/e2eValidation/regionSelector/Get-AvailableResourceLocation.ps1 b/avm/utilities/pipelines/e2eValidation/regionSelector/Get-AvailableResourceLocation.ps1 index 9aea0d4426..3ea25a2600 100644 --- a/avm/utilities/pipelines/e2eValidation/regionSelector/Get-AvailableResourceLocation.ps1 +++ b/avm/utilities/pipelines/e2eValidation/regionSelector/Get-AvailableResourceLocation.ps1 @@ -67,38 +67,47 @@ function Get-AvailableResourceLocation { # Configure Resource Type $fullModuleIdentifier = ($ModuleRoot -split '[\/|\\]{0,1}avm[\/|\\]{1}(res|ptn)[\/|\\]{1}')[2] -replace '\\', '/' - Write-Verbose "Full module identifier: $fullModuleIdentifier" - $formattedResourceType = Get-SpecsAlignedResourceName -ResourceIdentifier $fullModuleIdentifier -Verbose - Write-Verbose "Formatted resource type: $formattedResourceType" - - # Get the resource provider and resource name - $formattedResourceProvider = ($formattedResourceType -split '[\/|\\]{1}')[0] - Write-Verbose "Resource type: $formattedResourceProvider" - $formattedServiceName = ($formattedResourceType -split '[\/|\\]{1}')[1] - Write-Verbose "Resource: $formattedServiceName" - - $resourceRegionList = @() - $ResourceRegionList = (Get-AzResourceProvider | Where-Object { $_.ProviderNamespace -eq $formattedResourceProvider }).ResourceTypes | Where-Object { $_.ResourceTypeName -eq $formattedServiceName } | Select-Object -ExpandProperty Locations - Write-Verbose "Region list: $($resourceRegionList | ConvertTo-Json)" - - if ($resourceRegionList -eq 'global' -or $null -eq $resourceRegionList) { - Write-Verbose "Resource is global or does not have a location in the Resource Providers API, default region [$GlobalResourceGroupLocation] will be used for resource group creation" - $location = $GlobalResourceGroupLocation # Set Location to resource group location. Globabl resources should have hardocded location in `main.bicep` - } else { - $locations = Get-AzLocation | Where-Object { - $_.DisplayName -in $ResourceRegionList -and - $_.Location -notin $ExcludedRegions -and - $_.PairedRegion -ne '{}' -and - $_.RegionCategory -eq 'Recommended' - } | Select-Object -ExpandProperty Location - Write-Verbose "Available Locations: $($locations | ConvertTo-Json)" - - $filteredAllowedLocations = @($locations | Where-Object { $_ -in $AllowedRegionsList }) - Write-Verbose "Filtered allowed locations: $($filteredAllowedLocations | ConvertTo-Json)" - $index = Get-Random -Maximum ($filteredAllowedLocations.Count) + if ($ModuleRoot -like 'avm/res*') { + + Write-Verbose "Full module identifier: $fullModuleIdentifier" + $formattedResourceType = Get-SpecsAlignedResourceName -ResourceIdentifier $fullModuleIdentifier -Verbose + Write-Verbose "Formatted resource type: $formattedResourceType" + + # Get the resource provider and resource name + $formattedResourceProvider = ($formattedResourceType -split '[\/|\\]{1}')[0] + Write-Verbose "Resource type: $formattedResourceProvider" + $formattedServiceName = ($formattedResourceType -split '[\/|\\]{1}')[1] + Write-Verbose "Resource: $formattedServiceName" + + $resourceRegionList = @() + $ResourceRegionList = (Get-AzResourceProvider | Where-Object { $_.ProviderNamespace -eq $formattedResourceProvider }).ResourceTypes | Where-Object { $_.ResourceTypeName -eq $formattedServiceName } | Select-Object -ExpandProperty Locations + Write-Verbose "Region list: $($resourceRegionList | ConvertTo-Json)" + + if ($resourceRegionList -eq 'global' -or $null -eq $resourceRegionList) { + Write-Verbose "Resource is global or does not have a location in the Resource Providers API, default region [$GlobalResourceGroupLocation] will be used for resource group creation" + $location = $GlobalResourceGroupLocation # Set Location to resource group location. Globabl resources should have hardocded location in `main.bicep` + } else { + + $locations = Get-AzLocation | Where-Object { + $_.DisplayName -in $ResourceRegionList -and + $_.Location -notin $ExcludedRegions -and + $_.PairedRegion -ne '{}' -and + $_.RegionCategory -eq 'Recommended' + } | Select-Object -ExpandProperty Location + Write-Verbose "Available Locations: $($locations | ConvertTo-Json)" + + $filteredAllowedLocations = @($locations | Where-Object { $_ -in $AllowedRegionsList }) + Write-Verbose "Filtered allowed locations: $($filteredAllowedLocations | ConvertTo-Json)" + $index = Get-Random -Maximum ($filteredAllowedLocations.Count) + Write-Verbose "Generated random index [$index]" + $location = $filteredAllowedLocations[$index] + } + } else { + Write-Verbose 'Module is not resource so defaulting to the allowed region list' + $index = Get-Random -Maximum ($AllowedRegionsList.Count) Write-Verbose "Generated random index [$index]" - $location = $filteredAllowedLocations[$index] + $location = $AllowedRegionsList[$index] } Write-Verbose "Selected location [$location]" -Verbose From d0dadd0e92254cdd50ed02ca5fd52db5bc51ca3f Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Fri, 6 Sep 2024 16:26:58 +0100 Subject: [PATCH 22/29] chore: Remove trailing whitespace in main.json file --- avm/res/key-vault/vault/main.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avm/res/key-vault/vault/main.json b/avm/res/key-vault/vault/main.json index 218f0adae2..15f25dc8bb 100644 --- a/avm/res/key-vault/vault/main.json +++ b/avm/res/key-vault/vault/main.json @@ -2907,4 +2907,4 @@ } } } -} +} \ No newline at end of file From 75cc1788b93742ce5f1dfc9f56892d2c224c25f8 Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Fri, 7 Mar 2025 14:50:06 +0000 Subject: [PATCH 23/29] testing fix for PDNS Config #4345 --- avm/res/web/static-site/README.md | 34 + avm/res/web/static-site/main.bicep | 31 +- avm/res/web/static-site/main.json | 3277 +++++++++++++++++++++++++++- 3 files changed, 3231 insertions(+), 111 deletions(-) diff --git a/avm/res/web/static-site/README.md b/avm/res/web/static-site/README.md index fa75600ac0..721f1302c6 100644 --- a/avm/res/web/static-site/README.md +++ b/avm/res/web/static-site/README.md @@ -17,6 +17,16 @@ This module deploys a Static Web App. | :-- | :-- | | `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | | `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | +| `Microsoft.Network/privateDnsZones` | [2020-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones) | +| `Microsoft.Network/privateDnsZones/A` | [2020-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/A) | +| `Microsoft.Network/privateDnsZones/AAAA` | [2020-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/AAAA) | +| `Microsoft.Network/privateDnsZones/CNAME` | [2020-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/CNAME) | +| `Microsoft.Network/privateDnsZones/MX` | [2020-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/MX) | +| `Microsoft.Network/privateDnsZones/PTR` | [2020-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/PTR) | +| `Microsoft.Network/privateDnsZones/SOA` | [2020-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/SOA) | +| `Microsoft.Network/privateDnsZones/SRV` | [2020-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/SRV) | +| `Microsoft.Network/privateDnsZones/TXT` | [2020-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/TXT) | +| `Microsoft.Network/privateDnsZones/virtualNetworkLinks` | [2024-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-06-01/privateDnsZones/virtualNetworkLinks) | | `Microsoft.Network/privateEndpoints` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-11-01/privateEndpoints) | | `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-11-01/privateEndpoints/privateDnsZoneGroups) | | `Microsoft.Web/staticSites` | [2024-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Web/2024-04-01/staticSites) | @@ -633,6 +643,13 @@ param tags = { | [`tags`](#parameter-tags) | object | Tags of the resource. | | [`templateProperties`](#parameter-templateproperties) | object | Template Options for the static site. | +**Condiitonal parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`createPrivateDnsZone`](#parameter-createprivatednszone) | string | Due the nature of Azure Static Apps, a partition ID is added to the app URL upon creation. Enabling the creation of the private DNS Zone will provision a DNS Zone with the correct partition ID, this is required for private endpoint connectivity to be enabled. You can choose to disable this option and create your own private DNS Zone by leveraging the output of the partitionId within this module. Default is `Enabled`, However the Private Dns Zone will only be created following if a `privateEndpoint` configuration is supplied. | +| [`customPrivateDnsZoneResourceId`](#parameter-customprivatednszoneresourceid) | string | If you choose to create your own private DNS Zone, you can provide the resource ID of the private DNS Zone here. This is required if you have disabled the `createPrivateDnsZone` and have supplied a `privateEndpoint` configuration. | + ### Parameter: `name` The name of the static site. @@ -1389,6 +1406,22 @@ Template Options for the static site. - Required: No - Type: object +### Parameter: `createPrivateDnsZone` + +Due the nature of Azure Static Apps, a partition ID is added to the app URL upon creation. Enabling the creation of the private DNS Zone will provision a DNS Zone with the correct partition ID, this is required for private endpoint connectivity to be enabled. You can choose to disable this option and create your own private DNS Zone by leveraging the output of the partitionId within this module. Default is `Enabled`, However the Private Dns Zone will only be created following if a `privateEndpoint` configuration is supplied. + +- Required: No +- Type: string +- Default: `'Enabled'` + +### Parameter: `customPrivateDnsZoneResourceId` + +If you choose to create your own private DNS Zone, you can provide the resource ID of the private DNS Zone here. This is required if you have disabled the `createPrivateDnsZone` and have supplied a `privateEndpoint` configuration. + +- Required: No +- Type: string +- Default: `''` + ## Outputs | Output | Type | Description | @@ -1407,6 +1440,7 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | +| `br/public:avm/res/network/private-dns-zone:0.7.0` | Remote reference | | `br/public:avm/res/network/private-endpoint:0.10.1` | Remote reference | | `br/public:avm/utl/types/avm-common-types:0.5.1` | Remote reference | diff --git a/avm/res/web/static-site/main.bicep b/avm/res/web/static-site/main.bicep index a30f8d4e73..00ff9d58a0 100644 --- a/avm/res/web/static-site/main.bicep +++ b/avm/res/web/static-site/main.bicep @@ -257,6 +257,19 @@ resource staticSite_roleAssignments 'Microsoft.Authorization/roleAssignments@202 } ] +@description('Condiitonal. Due the nature of Azure Static Apps, a partition ID is added to the app URL upon creation. Enabling the creation of the private DNS Zone will provision a DNS Zone with the correct partition ID, this is required for private endpoint connectivity to be enabled. You can choose to disable this option and create your own private DNS Zone by leveraging the output of the partitionId within this module. Default is `Enabled`, However the Private Dns Zone will only be created following if a `privateEndpoint` configuration is supplied.') +param createPrivateDnsZone string = 'Enabled' + +@description('Condiitonal. If you choose to create your own private DNS Zone, you can provide the resource ID of the private DNS Zone here. This is required if you have disabled the `createPrivateDnsZone` and have supplied a `privateEndpoint` configuration.') +param customPrivateDnsZoneResourceId string = '' + +module staticSite_privateDnsZone 'br/public:avm/res/network/private-dns-zone:0.7.0' = if (!empty(privateEndpoints) && createPrivateDnsZone == 'Enabled') { + name: '${uniqueString(deployment().name, location)}-staticSite-PrivateDnsZone' + params: { + name: 'privatelink.${staticSite.properties.defaultHostname}.azurestaticapps.net' + } +} + module staticSite_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.10.1' = [ for (privateEndpoint, index) in (privateEndpoints ?? []): { name: '${uniqueString(deployment().name, location)}-staticSite-PrivateEndpoint-${index}' @@ -301,7 +314,23 @@ module staticSite_privateEndpoints 'br/public:avm/res/network/private-endpoint:0 'Full' ).location lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroup: privateEndpoint.?privateDnsZoneGroup + // privateDnsZoneGroup: privateEndpoint.?privateDnsZoneGroup + privateDnsZoneGroup: { + // privateDnsZoneGroupConfigs: (createPrivateDnsZone != 'Disabled') + // ? [ + // { + // privateDnsZoneResourceId: staticSite_privateDnsZone.outputs.resourceId + // } + // ] + // : [] + privateDnsZoneGroupConfigs: [ + { + privateDnsZoneResourceId: (createPrivateDnsZone != 'Disabled') + ? staticSite_privateDnsZone.outputs.resourceId + : customPrivateDnsZoneResourceId + } + ] + } roleAssignments: privateEndpoint.?roleAssignments tags: privateEndpoint.?tags ?? tags customDnsConfigs: privateEndpoint.?customDnsConfigs diff --git a/avm/res/web/static-site/main.json b/avm/res/web/static-site/main.json index c7c02ba510..54fe23cd29 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.33.93.31351", - "templateHash": "16463208866903865966" + "templateHash": "15883051576344218970" }, "name": "Static Web Apps", "description": "This module deploys a Static Web App." @@ -647,6 +647,20 @@ "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." } + }, + "createPrivateDnsZone": { + "type": "string", + "defaultValue": "Enabled", + "metadata": { + "description": "Condiitonal. Due the nature of Azure Static Apps, a partition ID is added to the app URL upon creation. Enabling the creation of the private DNS Zone will provision a DNS Zone with the correct partition ID, this is required for private endpoint connectivity to be enabled. You can choose to disable this option and create your own private DNS Zone by leveraging the output of the partitionId within this module. Default is `Enabled`, However the Private Dns Zone will only be created following if a `privateEndpoint` configuration is supplied." + } + }, + "customPrivateDnsZoneResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Condiitonal. If you choose to create your own private DNS Zone, you can provide the resource ID of the private DNS Zone here. This is required if you have disabled the `createPrivateDnsZone` and have supplied a `privateEndpoint` configuration." + } } }, "variables": { @@ -996,136 +1010,3172 @@ "description": "Required. App settings." } }, - "staticSiteName": { - "type": "string", - "metadata": { - "description": "Conditional. The name of the parent Static Web App. Required if the template is used in a standalone deployment." - } + "staticSiteName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Static Web App. Required if the template is used in a standalone deployment." + } + } + }, + "resources": [ + { + "type": "Microsoft.Web/staticSites/config", + "apiVersion": "2022-03-01", + "name": "[format('{0}/{1}', parameters('staticSiteName'), parameters('kind'))]", + "properties": "[parameters('properties')]" + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the config." + }, + "value": "[parameters('kind')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the config." + }, + "value": "[resourceId('Microsoft.Web/staticSites/config', parameters('staticSiteName'), parameters('kind'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the config was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "staticSite" + ] + }, + "staticSite_customDomains": { + "copy": { + "name": "staticSite_customDomains", + "count": "[length(parameters('customDomains'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-StaticSite-customDomains-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('customDomains')[copyIndex()]]" + }, + "staticSiteName": { + "value": "[parameters('name')]" + }, + "validationMethod": "[if(equals(indexOf(parameters('customDomains')[copyIndex()], '.'), lastIndexOf(parameters('customDomains')[copyIndex()], '.')), createObject('value', 'dns-txt-token'), createObject('value', 'cname-delegation'))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.33.93.31351", + "templateHash": "10915453834048667608" + }, + "name": "Static Web App Site Custom Domains", + "description": "This module deploys a Static Web App Site Custom Domain." + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The custom domain name." + } + }, + "staticSiteName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Static Web App. Required if the template is used in a standalone deployment." + } + }, + "validationMethod": { + "type": "string", + "defaultValue": "cname-delegation", + "metadata": { + "description": "Optional. Validation method for adding a custom domain." + } + } + }, + "resources": [ + { + "type": "Microsoft.Web/staticSites/customDomains", + "apiVersion": "2022-03-01", + "name": "[format('{0}/{1}', parameters('staticSiteName'), parameters('name'))]", + "properties": { + "validationMethod": "[parameters('validationMethod')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the static site custom domain." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the static site custom domain." + }, + "value": "[resourceId('Microsoft.Web/staticSites/customDomains', parameters('staticSiteName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the static site custom domain was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "staticSite" + ] + }, + "staticSite_privateDnsZone": { + "condition": "[and(not(empty(parameters('privateEndpoints'))), equals(parameters('createPrivateDnsZone'), 'Enabled'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-staticSite-PrivateDnsZone', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('privatelink.{0}.azurestaticapps.net', reference('staticSite').defaultHostname)]" + } + }, + "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.32.4.45862", + "templateHash": "83178825086050429" + }, + "name": "Private DNS Zones", + "description": "This module deploys a Private DNS zone.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "aType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "aRecords": { + "type": "array", + "items": { + "type": "object", + "properties": { + "ipv4Address": { + "type": "string", + "metadata": { + "description": "Required. The IPv4 address of this A record." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of A records in the record set." + } + } + } + }, + "nullable": true + }, + "aaaaType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "aaaaRecords": { + "type": "array", + "items": { + "type": "object", + "properties": { + "ipv6Address": { + "type": "string", + "metadata": { + "description": "Required. The IPv6 address of this AAAA record." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of AAAA records in the record set." + } + } + } + }, + "nullable": true + }, + "cnameType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "cnameRecord": { + "type": "object", + "properties": { + "cname": { + "type": "string", + "metadata": { + "description": "Required. The canonical name of the CNAME record." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The CNAME record in the record set." + } + } + } + }, + "nullable": true + }, + "mxType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "mxRecords": { + "type": "array", + "items": { + "type": "object", + "properties": { + "exchange": { + "type": "string", + "metadata": { + "description": "Required. The domain name of the mail host for this MX record." + } + }, + "preference": { + "type": "int", + "metadata": { + "description": "Required. The preference value for this MX record." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of MX records in the record set." + } + } + } + }, + "nullable": true + }, + "ptrType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "ptrRecords": { + "type": "array", + "items": { + "type": "object", + "properties": { + "ptrdname": { + "type": "string", + "metadata": { + "description": "Required. The PTR target domain name for this PTR record." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of PTR records in the record set." + } + } + } + }, + "nullable": true + }, + "soaType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "soaRecord": { + "type": "object", + "properties": { + "email": { + "type": "string", + "metadata": { + "description": "Required. The email contact for this SOA record." + } + }, + "expireTime": { + "type": "int", + "metadata": { + "description": "Required. The expire time for this SOA record." + } + }, + "host": { + "type": "string", + "metadata": { + "description": "Required. The domain name of the authoritative name server for this SOA record." + } + }, + "minimumTtl": { + "type": "int", + "metadata": { + "description": "Required. The minimum value for this SOA record. By convention this is used to determine the negative caching duration." + } + }, + "refreshTime": { + "type": "int", + "metadata": { + "description": "Required. The refresh value for this SOA record." + } + }, + "retryTime": { + "type": "int", + "metadata": { + "description": "Required. The retry time for this SOA record." + } + }, + "serialNumber": { + "type": "int", + "metadata": { + "description": "Required. The serial number for this SOA record." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The SOA record in the record set." + } + } + } + }, + "nullable": true + }, + "srvType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "srvRecords": { + "type": "array", + "items": { + "type": "object", + "properties": { + "priority": { + "type": "int", + "metadata": { + "description": "Required. The priority value for this SRV record." + } + }, + "weight": { + "type": "int", + "metadata": { + "description": "Required. The weight value for this SRV record." + } + }, + "port": { + "type": "int", + "metadata": { + "description": "Required. The port value for this SRV record." + } + }, + "target": { + "type": "string", + "metadata": { + "description": "Required. The target domain name for this SRV record." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of SRV records in the record set." + } + } + } + }, + "nullable": true + }, + "txtType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata of the record." + } + }, + "ttl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The TTL of the record." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "txtRecords": { + "type": "array", + "items": { + "type": "object", + "properties": { + "value": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The text value of this TXT record." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The list of TXT records in the record set." + } + } + } + }, + "nullable": true + }, + "virtualNetworkLinkType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "minLength": 1, + "maxLength": 80, + "metadata": { + "description": "Optional. The resource name." + } + }, + "virtualNetworkResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the virtual network to link." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Azure Region where the resource lives." + } + }, + "registrationEnabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Is auto-registration of virtual machine records in the virtual network in the Private DNS zone enabled?." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "resolutionPolicy": { + "type": "string", + "allowedValues": [ + "Default", + "NxDomainRedirect" + ], + "nullable": true, + "metadata": { + "description": "Optional. The resolution type of the private-dns-zone fallback machanism." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Private DNS zone name." + } + }, + "a": { + "$ref": "#/definitions/aType", + "metadata": { + "description": "Optional. Array of A records." + } + }, + "aaaa": { + "$ref": "#/definitions/aaaaType", + "metadata": { + "description": "Optional. Array of AAAA records." + } + }, + "cname": { + "$ref": "#/definitions/cnameType", + "metadata": { + "description": "Optional. Array of CNAME records." + } + }, + "mx": { + "$ref": "#/definitions/mxType", + "metadata": { + "description": "Optional. Array of MX records." + } + }, + "ptr": { + "$ref": "#/definitions/ptrType", + "metadata": { + "description": "Optional. Array of PTR records." + } + }, + "soa": { + "$ref": "#/definitions/soaType", + "metadata": { + "description": "Optional. Array of SOA records." + } + }, + "srv": { + "$ref": "#/definitions/srvType", + "metadata": { + "description": "Optional. Array of SRV records." + } + }, + "txt": { + "$ref": "#/definitions/txtType", + "metadata": { + "description": "Optional. Array of TXT records." + } + }, + "virtualNetworkLinks": { + "$ref": "#/definitions/virtualNetworkLinkType", + "metadata": { + "description": "Optional. Array of custom objects describing vNet links of the DNS zone. Each object should contain properties 'virtualNetworkResourceId' and 'registrationEnabled'. The 'vnetResourceId' is a resource ID of a vNet to link, 'registrationEnabled' (bool) enables automatic DNS registration in the zone for the linked vNet." + } + }, + "location": { + "type": "string", + "defaultValue": "global", + "metadata": { + "description": "Optional. The location of the PrivateDNSZone. Should be global." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.network-privatednszone.{0}.{1}', replace('0.7.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "privateDnsZone": { + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]" + }, + "privateDnsZone_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_roleAssignments": { + "copy": { + "name": "privateDnsZone_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_A": { + "copy": { + "name": "privateDnsZone_A", + "count": "[length(coalesce(parameters('a'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-ARecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('a'), createArray())[copyIndex()].name]" + }, + "aRecords": { + "value": "[tryGet(coalesce(parameters('a'), createArray())[copyIndex()], 'aRecords')]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('a'), createArray())[copyIndex()], 'metadata')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('a'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('a'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.32.4.45862", + "templateHash": "2531120132215940282" + }, + "name": "Private DNS Zone A record", + "description": "This module deploys a Private DNS Zone A record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the A record." + } + }, + "aRecords": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of A records in the record set." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "A": { + "type": "Microsoft.Network/privateDnsZones/A", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "aRecords": "[parameters('aRecords')]", + "metadata": "[parameters('metadata')]", + "ttl": "[parameters('ttl')]" + } + }, + "A_roleAssignments": { + "copy": { + "name": "A_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/A/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/A', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "A" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed A record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed A record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/A', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed A record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_AAAA": { + "copy": { + "name": "privateDnsZone_AAAA", + "count": "[length(coalesce(parameters('aaaa'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-AAAARecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('aaaa'), createArray())[copyIndex()].name]" + }, + "aaaaRecords": { + "value": "[tryGet(coalesce(parameters('aaaa'), createArray())[copyIndex()], 'aaaaRecords')]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('aaaa'), createArray())[copyIndex()], 'metadata')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('aaaa'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('aaaa'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.32.4.45862", + "templateHash": "16709340450244912125" + }, + "name": "Private DNS Zone AAAA record", + "description": "This module deploys a Private DNS Zone AAAA record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the AAAA record." + } + }, + "aaaaRecords": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of AAAA records in the record set." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "AAAA": { + "type": "Microsoft.Network/privateDnsZones/AAAA", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "aaaaRecords": "[parameters('aaaaRecords')]", + "metadata": "[parameters('metadata')]", + "ttl": "[parameters('ttl')]" + } + }, + "AAAA_roleAssignments": { + "copy": { + "name": "AAAA_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/AAAA/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/AAAA', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "AAAA" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed AAAA record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed AAAA record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/AAAA', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed AAAA record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_CNAME": { + "copy": { + "name": "privateDnsZone_CNAME", + "count": "[length(coalesce(parameters('cname'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-CNAMERecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('cname'), createArray())[copyIndex()].name]" + }, + "cnameRecord": { + "value": "[tryGet(coalesce(parameters('cname'), createArray())[copyIndex()], 'cnameRecord')]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('cname'), createArray())[copyIndex()], 'metadata')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('cname'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('cname'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.32.4.45862", + "templateHash": "9976020649752073181" + }, + "name": "Private DNS Zone CNAME record", + "description": "This module deploys a Private DNS Zone CNAME record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the CNAME record." + } + }, + "cnameRecord": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. A CNAME record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "CNAME": { + "type": "Microsoft.Network/privateDnsZones/CNAME", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "cnameRecord": "[parameters('cnameRecord')]", + "metadata": "[parameters('metadata')]", + "ttl": "[parameters('ttl')]" + } + }, + "CNAME_roleAssignments": { + "copy": { + "name": "CNAME_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/CNAME/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/CNAME', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "CNAME" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed CNAME record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed CNAME record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/CNAME', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed CNAME record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_MX": { + "copy": { + "name": "privateDnsZone_MX", + "count": "[length(coalesce(parameters('mx'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-MXRecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('mx'), createArray())[copyIndex()].name]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('mx'), createArray())[copyIndex()], 'metadata')]" + }, + "mxRecords": { + "value": "[tryGet(coalesce(parameters('mx'), createArray())[copyIndex()], 'mxRecords')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('mx'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('mx'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.32.4.45862", + "templateHash": "2520323624213076361" + }, + "name": "Private DNS Zone MX record", + "description": "This module deploys a Private DNS Zone MX record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the MX record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "mxRecords": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of MX records in the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "MX": { + "type": "Microsoft.Network/privateDnsZones/MX", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]", + "mxRecords": "[parameters('mxRecords')]", + "ttl": "[parameters('ttl')]" + } + }, + "MX_roleAssignments": { + "copy": { + "name": "MX_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/MX/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/MX', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "MX" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed MX record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed MX record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/MX', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed MX record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_PTR": { + "copy": { + "name": "privateDnsZone_PTR", + "count": "[length(coalesce(parameters('ptr'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-PTRRecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('ptr'), createArray())[copyIndex()].name]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('ptr'), createArray())[copyIndex()], 'metadata')]" + }, + "ptrRecords": { + "value": "[tryGet(coalesce(parameters('ptr'), createArray())[copyIndex()], 'ptrRecords')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('ptr'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('ptr'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.32.4.45862", + "templateHash": "3080404733048745471" + }, + "name": "Private DNS Zone PTR record", + "description": "This module deploys a Private DNS Zone PTR record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the PTR record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "ptrRecords": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of PTR records in the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "PTR": { + "type": "Microsoft.Network/privateDnsZones/PTR", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]", + "ptrRecords": "[parameters('ptrRecords')]", + "ttl": "[parameters('ttl')]" + } + }, + "PTR_roleAssignments": { + "copy": { + "name": "PTR_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/PTR/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/PTR', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "PTR" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed PTR record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed PTR record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/PTR', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed PTR record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_SOA": { + "copy": { + "name": "privateDnsZone_SOA", + "count": "[length(coalesce(parameters('soa'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-SOARecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('soa'), createArray())[copyIndex()].name]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('soa'), createArray())[copyIndex()], 'metadata')]" + }, + "soaRecord": { + "value": "[tryGet(coalesce(parameters('soa'), createArray())[copyIndex()], 'soaRecord')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('soa'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('soa'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.32.4.45862", + "templateHash": "6653951445614700931" + }, + "name": "Private DNS Zone SOA record", + "description": "This module deploys a Private DNS Zone SOA record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the SOA record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "soaRecord": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. A SOA record." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "SOA": { + "type": "Microsoft.Network/privateDnsZones/SOA", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]", + "soaRecord": "[parameters('soaRecord')]", + "ttl": "[parameters('ttl')]" + } + }, + "SOA_roleAssignments": { + "copy": { + "name": "SOA_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/SOA/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/SOA', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "SOA" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed SOA record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed SOA record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/SOA', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed SOA record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_SRV": { + "copy": { + "name": "privateDnsZone_SRV", + "count": "[length(coalesce(parameters('srv'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-SRVRecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('srv'), createArray())[copyIndex()].name]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('srv'), createArray())[copyIndex()], 'metadata')]" + }, + "srvRecords": { + "value": "[tryGet(coalesce(parameters('srv'), createArray())[copyIndex()], 'srvRecords')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('srv'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('srv'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.32.4.45862", + "templateHash": "5790774778713328446" + }, + "name": "Private DNS Zone SRV record", + "description": "This module deploys a Private DNS Zone SRV record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the SRV record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "srvRecords": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of SRV records in the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "SRV": { + "type": "Microsoft.Network/privateDnsZones/SRV", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]", + "srvRecords": "[parameters('srvRecords')]", + "ttl": "[parameters('ttl')]" + } + }, + "SRV_roleAssignments": { + "copy": { + "name": "SRV_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/SRV/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/SRV', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "SRV" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed SRV record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed SRV record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/SRV', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed SRV record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_TXT": { + "copy": { + "name": "privateDnsZone_TXT", + "count": "[length(coalesce(parameters('txt'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-TXTRecord-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('txt'), createArray())[copyIndex()].name]" + }, + "metadata": { + "value": "[tryGet(coalesce(parameters('txt'), createArray())[copyIndex()], 'metadata')]" + }, + "txtRecords": { + "value": "[tryGet(coalesce(parameters('txt'), createArray())[copyIndex()], 'txtRecords')]" + }, + "ttl": { + "value": "[coalesce(tryGet(coalesce(parameters('txt'), createArray())[copyIndex()], 'ttl'), 3600)]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('txt'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.32.4.45862", + "templateHash": "1855369119498044639" + }, + "name": "Private DNS Zone TXT record", + "description": "This module deploys a Private DNS Zone TXT record.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the TXT record." + } + }, + "metadata": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The metadata attached to the record set." + } + }, + "ttl": { + "type": "int", + "defaultValue": 3600, + "metadata": { + "description": "Optional. The TTL (time-to-live) of the records in the record set." + } + }, + "txtRecords": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The list of TXT records in the record set." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "TXT": { + "type": "Microsoft.Network/privateDnsZones/TXT", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]", + "ttl": "[parameters('ttl')]", + "txtRecords": "[parameters('txtRecords')]" + } + }, + "TXT_roleAssignments": { + "copy": { + "name": "TXT_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateDnsZones/{0}/TXT/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateDnsZones/TXT', parameters('privateDnsZoneName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "TXT" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed TXT record." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed TXT record." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/TXT', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed TXT record." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] + }, + "privateDnsZone_virtualNetworkLinks": { + "copy": { + "name": "privateDnsZone_virtualNetworkLinks", + "count": "[length(coalesce(parameters('virtualNetworkLinks'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateDnsZone-VirtualNetworkLink-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(tryGet(coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()], 'name'), format('{0}-vnetlink', last(split(coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()].virtualNetworkResourceId, '/'))))]" + }, + "virtualNetworkResourceId": { + "value": "[coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()].virtualNetworkResourceId]" + }, + "location": { + "value": "[coalesce(tryGet(coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()], 'location'), 'global')]" + }, + "registrationEnabled": { + "value": "[coalesce(tryGet(coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()], 'registrationEnabled'), false())]" + }, + "tags": { + "value": "[coalesce(tryGet(coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" + }, + "resolutionPolicy": { + "value": "[tryGet(coalesce(parameters('virtualNetworkLinks'), createArray())[copyIndex()], 'resolutionPolicy')]" + } + }, + "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.32.4.45862", + "templateHash": "15326596012552051215" + }, + "name": "Private DNS Zone Virtual Network Link", + "description": "This module deploys a Private DNS Zone Virtual Network Link.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "privateDnsZoneName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Private DNS zone. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "defaultValue": "[format('{0}-vnetlink', last(split(parameters('virtualNetworkResourceId'), '/')))]", + "metadata": { + "description": "Optional. The name of the virtual network link." + } + }, + "location": { + "type": "string", + "defaultValue": "global", + "metadata": { + "description": "Optional. The location of the PrivateDNSZone. Should be global." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "registrationEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Is auto-registration of virtual machine records in the virtual network in the Private DNS zone enabled?." + } + }, + "virtualNetworkResourceId": { + "type": "string", + "metadata": { + "description": "Required. Link to another virtual network resource ID." + } + }, + "resolutionPolicy": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resolution policy on the virtual network link. Only applicable for virtual network links to privatelink zones, and for A,AAAA,CNAME queries. When set to `NxDomainRedirect`, Azure DNS resolver falls back to public resolution if private dns query resolution results in non-existent domain response. `Default` is configured as the default option." + } + } + }, + "resources": { + "privateDnsZone": { + "existing": true, + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[parameters('privateDnsZoneName')]" + }, + "virtualNetworkLink": { + "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", + "apiVersion": "2024-06-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "registrationEnabled": "[parameters('registrationEnabled')]", + "virtualNetwork": { + "id": "[parameters('virtualNetworkResourceId')]" + }, + "resolutionPolicy": "[parameters('resolutionPolicy')]" + } + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed virtual network link." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed virtual network link." + }, + "value": "[resourceId('Microsoft.Network/privateDnsZones/virtualNetworkLinks', parameters('privateDnsZoneName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed virtual network link." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('virtualNetworkLink', '2024-06-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "privateDnsZone" + ] } }, - "resources": [ - { - "type": "Microsoft.Web/staticSites/config", - "apiVersion": "2022-03-01", - "name": "[format('{0}/{1}', parameters('staticSiteName'), parameters('kind'))]", - "properties": "[parameters('properties')]" - } - ], "outputs": { - "name": { - "type": "string", - "metadata": { - "description": "The name of the config." - }, - "value": "[parameters('kind')]" - }, - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the config." - }, - "value": "[resourceId('Microsoft.Web/staticSites/config', parameters('staticSiteName'), parameters('kind'))]" - }, "resourceGroupName": { "type": "string", "metadata": { - "description": "The name of the resource group the config was created in." + "description": "The resource group the private DNS zone was deployed into." }, "value": "[resourceGroup().name]" - } - } - } - }, - "dependsOn": [ - "staticSite" - ] - }, - "staticSite_customDomains": { - "copy": { - "name": "staticSite_customDomains", - "count": "[length(parameters('customDomains'))]" - }, - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('{0}-StaticSite-customDomains-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "name": { - "value": "[parameters('customDomains')[copyIndex()]]" - }, - "staticSiteName": { - "value": "[parameters('name')]" - }, - "validationMethod": "[if(equals(indexOf(parameters('customDomains')[copyIndex()], '.'), lastIndexOf(parameters('customDomains')[copyIndex()], '.')), createObject('value', 'dns-txt-token'), createObject('value', 'cname-delegation'))]" - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.33.93.31351", - "templateHash": "10915453834048667608" - }, - "name": "Static Web App Site Custom Domains", - "description": "This module deploys a Static Web App Site Custom Domain." - }, - "parameters": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The custom domain name." - } - }, - "staticSiteName": { - "type": "string", - "metadata": { - "description": "Conditional. The name of the parent Static Web App. Required if the template is used in a standalone deployment." - } }, - "validationMethod": { - "type": "string", - "defaultValue": "cname-delegation", - "metadata": { - "description": "Optional. Validation method for adding a custom domain." - } - } - }, - "resources": [ - { - "type": "Microsoft.Web/staticSites/customDomains", - "apiVersion": "2022-03-01", - "name": "[format('{0}/{1}', parameters('staticSiteName'), parameters('name'))]", - "properties": { - "validationMethod": "[parameters('validationMethod')]" - } - } - ], - "outputs": { "name": { "type": "string", "metadata": { - "description": "The name of the static site custom domain." + "description": "The name of the private DNS zone." }, "value": "[parameters('name')]" }, "resourceId": { "type": "string", "metadata": { - "description": "The resource ID of the static site custom domain." + "description": "The resource ID of the private DNS zone." }, - "value": "[resourceId('Microsoft.Web/staticSites/customDomains', parameters('staticSiteName'), parameters('name'))]" + "value": "[resourceId('Microsoft.Network/privateDnsZones', parameters('name'))]" }, - "resourceGroupName": { + "location": { "type": "string", "metadata": { - "description": "The resource group the static site custom domain was deployed into." + "description": "The location the resource was deployed into." }, - "value": "[resourceGroup().name]" + "value": "[reference('privateDnsZone', '2020-06-01', 'full').location]" } } } @@ -1168,7 +4218,13 @@ "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'lock'), parameters('lock'))]" }, "privateDnsZoneGroup": { - "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneGroup')]" + "value": { + "privateDnsZoneGroupConfigs": [ + { + "privateDnsZoneResourceId": "[if(not(equals(parameters('createPrivateDnsZone'), 'Disabled')), reference('staticSite_privateDnsZone').outputs.resourceId.value, parameters('customPrivateDnsZoneResourceId'))]" + } + ] + } }, "roleAssignments": { "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'roleAssignments')]" @@ -1888,7 +4944,8 @@ } }, "dependsOn": [ - "staticSite" + "staticSite", + "staticSite_privateDnsZone" ] } }, From 0bd83889a8f689a6c336d36985bebd561618ab9f Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Fri, 7 Mar 2025 15:08:20 +0000 Subject: [PATCH 24/29] adding telem ref --- avm/res/web/static-site/README.md | 7 +++++++ avm/res/web/static-site/main.bicep | 17 +++++++++++------ avm/res/web/static-site/main.json | 9 ++++++++- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/avm/res/web/static-site/README.md b/avm/res/web/static-site/README.md index 721f1302c6..96be549f48 100644 --- a/avm/res/web/static-site/README.md +++ b/avm/res/web/static-site/README.md @@ -1413,6 +1413,13 @@ Due the nature of Azure Static Apps, a partition ID is added to the app URL upon - Required: No - Type: string - Default: `'Enabled'` +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` ### Parameter: `customPrivateDnsZoneResourceId` diff --git a/avm/res/web/static-site/main.bicep b/avm/res/web/static-site/main.bicep index 00ff9d58a0..9d487c1a32 100644 --- a/avm/res/web/static-site/main.bicep +++ b/avm/res/web/static-site/main.bicep @@ -96,6 +96,16 @@ param customDomains array = [] ]) param publicNetworkAccess string = '' +@description('Condiitonal. Due the nature of Azure Static Apps, a partition ID is added to the app URL upon creation. Enabling the creation of the private DNS Zone will provision a DNS Zone with the correct partition ID, this is required for private endpoint connectivity to be enabled. You can choose to disable this option and create your own private DNS Zone by leveraging the output of the partitionId within this module. Default is `Enabled`, However the Private Dns Zone will only be created following if a `privateEndpoint` configuration is supplied.') +@allowed([ + 'Enabled' + 'Disabled' +]) +param createPrivateDnsZone string = 'Enabled' + +@description('Condiitonal. If you choose to create your own private DNS Zone, you can provide the resource ID of the private DNS Zone here. This is required if you have disabled the `createPrivateDnsZone` and have supplied a `privateEndpoint` configuration.') +param customPrivateDnsZoneResourceId string = '' + var enableReferencedModulesTelemetry = false var formattedUserAssignedIdentities = reduce( @@ -257,16 +267,11 @@ resource staticSite_roleAssignments 'Microsoft.Authorization/roleAssignments@202 } ] -@description('Condiitonal. Due the nature of Azure Static Apps, a partition ID is added to the app URL upon creation. Enabling the creation of the private DNS Zone will provision a DNS Zone with the correct partition ID, this is required for private endpoint connectivity to be enabled. You can choose to disable this option and create your own private DNS Zone by leveraging the output of the partitionId within this module. Default is `Enabled`, However the Private Dns Zone will only be created following if a `privateEndpoint` configuration is supplied.') -param createPrivateDnsZone string = 'Enabled' - -@description('Condiitonal. If you choose to create your own private DNS Zone, you can provide the resource ID of the private DNS Zone here. This is required if you have disabled the `createPrivateDnsZone` and have supplied a `privateEndpoint` configuration.') -param customPrivateDnsZoneResourceId string = '' - module staticSite_privateDnsZone 'br/public:avm/res/network/private-dns-zone:0.7.0' = if (!empty(privateEndpoints) && createPrivateDnsZone == 'Enabled') { name: '${uniqueString(deployment().name, location)}-staticSite-PrivateDnsZone' params: { name: 'privatelink.${staticSite.properties.defaultHostname}.azurestaticapps.net' + enableTelemetry: enableReferencedModulesTelemetry } } diff --git a/avm/res/web/static-site/main.json b/avm/res/web/static-site/main.json index 54fe23cd29..85ce2cb229 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.33.93.31351", - "templateHash": "15883051576344218970" + "templateHash": "16601307140722570602" }, "name": "Static Web Apps", "description": "This module deploys a Static Web App." @@ -651,6 +651,10 @@ "createPrivateDnsZone": { "type": "string", "defaultValue": "Enabled", + "allowedValues": [ + "Enabled", + "Disabled" + ], "metadata": { "description": "Condiitonal. Due the nature of Azure Static Apps, a partition ID is added to the app URL upon creation. Enabling the creation of the private DNS Zone will provision a DNS Zone with the correct partition ID, this is required for private endpoint connectivity to be enabled. You can choose to disable this option and create your own private DNS Zone by leveraging the output of the partitionId within this module. Default is `Enabled`, However the Private Dns Zone will only be created following if a `privateEndpoint` configuration is supplied." } @@ -1161,6 +1165,9 @@ "parameters": { "name": { "value": "[format('privatelink.{0}.azurestaticapps.net', reference('staticSite').defaultHostname)]" + }, + "enableTelemetry": { + "value": "[variables('enableReferencedModulesTelemetry')]" } }, "template": { From 5010596a6fe755d49759e33ef6f58afac30ae239 Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Tue, 11 Mar 2025 07:10:34 +0000 Subject: [PATCH 25/29] [AVM Module Issue]: var identity is constructed incorrectly on several templates #4701 --- avm/res/web/static-site/main.bicep | 2 +- avm/res/web/static-site/main.json | 4 ++-- avm/res/web/static-site/version.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/avm/res/web/static-site/main.bicep b/avm/res/web/static-site/main.bicep index 9d487c1a32..37e105e411 100644 --- a/avm/res/web/static-site/main.bicep +++ b/avm/res/web/static-site/main.bicep @@ -118,7 +118,7 @@ var identity = !empty(managedIdentities) ? { type: (managedIdentities.?systemAssigned ?? false) ? (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned, UserAssigned' : 'SystemAssigned') - : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null) + : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : 'None') userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null } : null diff --git a/avm/res/web/static-site/main.json b/avm/res/web/static-site/main.json index 85ce2cb229..ba17da4b50 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.33.93.31351", - "templateHash": "16601307140722570602" + "templateHash": "14731505669091564649" }, "name": "Static Web Apps", "description": "This module deploys a Static Web App." @@ -677,7 +677,7 @@ ], "enableReferencedModulesTelemetry": 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'))))]", - "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/web/static-site/version.json b/avm/res/web/static-site/version.json index b6668657e7..b39a201436 100644 --- a/avm/res/web/static-site/version.json +++ b/avm/res/web/static-site/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.8", + "version": "0.9", "pathFilters": [ "./main.json" ] From 4e5d33bb4eba6dbddffc57613a2e21814d4e9df0 Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Fri, 14 Mar 2025 10:03:29 +0000 Subject: [PATCH 26/29] feat: add virtualNetworkResourceId output and parameter for private DNS Zone configuration --- avm/res/web/static-site/README.md | 51 +++++++--- avm/res/web/static-site/main.bicep | 98 +++++++++++++++++-- avm/res/web/static-site/main.json | 18 +++- .../tests/e2e/max/dependencies.bicep | 3 + .../static-site/tests/e2e/max/main.test.bicep | 1 + 5 files changed, 144 insertions(+), 27 deletions(-) diff --git a/avm/res/web/static-site/README.md b/avm/res/web/static-site/README.md index 96be549f48..1bc76b9dab 100644 --- a/avm/res/web/static-site/README.md +++ b/avm/res/web/static-site/README.md @@ -193,6 +193,7 @@ module staticSite 'br/public:avm/res/web/static-site:' = { 'hidden-title': 'This is visible in the resource name' Role: 'DeploymentValidation' } + virtualNetworkResourceId: '' } } ``` @@ -319,6 +320,9 @@ module staticSite 'br/public:avm/res/web/static-site:' = { "hidden-title": "This is visible in the resource name", "Role": "DeploymentValidation" } + }, + "virtualNetworkResourceId": { + "value": "" } } } @@ -415,6 +419,7 @@ param tags = { 'hidden-title': 'This is visible in the resource name' Role: 'DeploymentValidation' } +param virtualNetworkResourceId = '' ``` @@ -616,6 +621,13 @@ param tags = { | :-- | :-- | :-- | | [`name`](#parameter-name) | string | The name of the static site. | +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`createPrivateDnsZone`](#parameter-createprivatednszone) | string | Due the nature of Azure Static Apps, a partition ID is added to the app URL upon creation. Enabling the creation of the private DNS Zone will provision a DNS Zone with the correct partition ID, this is required for private endpoint connectivity to be enabled. You can choose to disable this option and create your own private DNS Zone by leveraging the output of the partitionId within this module. Default is `Enabled`, However the Private DNS Zone will only be created following if a `privateEndpoint` configuration is supplied. | +| [`virtualNetworkResourceId`](#parameter-virtualnetworkresourceid) | string | The Virtual Network Resource Id to use for the private DNS Zone Vnet Link. Only used if `createPrivateDnsZone` is set to `Enabled` and a Private Endpoint Configuration hs been supplied. | + **Optional parameters** | Parameter | Type | Description | @@ -647,7 +659,6 @@ param tags = { | Parameter | Type | Description | | :-- | :-- | :-- | -| [`createPrivateDnsZone`](#parameter-createprivatednszone) | string | Due the nature of Azure Static Apps, a partition ID is added to the app URL upon creation. Enabling the creation of the private DNS Zone will provision a DNS Zone with the correct partition ID, this is required for private endpoint connectivity to be enabled. You can choose to disable this option and create your own private DNS Zone by leveraging the output of the partitionId within this module. Default is `Enabled`, However the Private Dns Zone will only be created following if a `privateEndpoint` configuration is supplied. | | [`customPrivateDnsZoneResourceId`](#parameter-customprivatednszoneresourceid) | string | If you choose to create your own private DNS Zone, you can provide the resource ID of the private DNS Zone here. This is required if you have disabled the `createPrivateDnsZone` and have supplied a `privateEndpoint` configuration. | ### Parameter: `name` @@ -657,6 +668,29 @@ The name of the static site. - Required: Yes - Type: string +### Parameter: `createPrivateDnsZone` + +Due the nature of Azure Static Apps, a partition ID is added to the app URL upon creation. Enabling the creation of the private DNS Zone will provision a DNS Zone with the correct partition ID, this is required for private endpoint connectivity to be enabled. You can choose to disable this option and create your own private DNS Zone by leveraging the output of the partitionId within this module. Default is `Enabled`, However the Private DNS Zone will only be created following if a `privateEndpoint` configuration is supplied. + +- Required: No +- Type: string +- Default: `'Enabled'` +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `virtualNetworkResourceId` + +The Virtual Network Resource Id to use for the private DNS Zone Vnet Link. Only used if `createPrivateDnsZone` is set to `Enabled` and a Private Endpoint Configuration hs been supplied. + +- Required: No +- Type: string +- Default: `''` + ### Parameter: `allowConfigFileUpdates` False if config file is locked for this static web app; otherwise, true. @@ -1406,21 +1440,6 @@ Template Options for the static site. - Required: No - Type: object -### Parameter: `createPrivateDnsZone` - -Due the nature of Azure Static Apps, a partition ID is added to the app URL upon creation. Enabling the creation of the private DNS Zone will provision a DNS Zone with the correct partition ID, this is required for private endpoint connectivity to be enabled. You can choose to disable this option and create your own private DNS Zone by leveraging the output of the partitionId within this module. Default is `Enabled`, However the Private Dns Zone will only be created following if a `privateEndpoint` configuration is supplied. - -- Required: No -- Type: string -- Default: `'Enabled'` -- Allowed: - ```Bicep - [ - 'Disabled' - 'Enabled' - ] - ``` - ### Parameter: `customPrivateDnsZoneResourceId` If you choose to create your own private DNS Zone, you can provide the resource ID of the private DNS Zone here. This is required if you have disabled the `createPrivateDnsZone` and have supplied a `privateEndpoint` configuration. diff --git a/avm/res/web/static-site/main.bicep b/avm/res/web/static-site/main.bicep index 37e105e411..20b1d3786a 100644 --- a/avm/res/web/static-site/main.bicep +++ b/avm/res/web/static-site/main.bicep @@ -96,13 +96,16 @@ param customDomains array = [] ]) param publicNetworkAccess string = '' -@description('Condiitonal. Due the nature of Azure Static Apps, a partition ID is added to the app URL upon creation. Enabling the creation of the private DNS Zone will provision a DNS Zone with the correct partition ID, this is required for private endpoint connectivity to be enabled. You can choose to disable this option and create your own private DNS Zone by leveraging the output of the partitionId within this module. Default is `Enabled`, However the Private Dns Zone will only be created following if a `privateEndpoint` configuration is supplied.') +@description('Conditional. Due the nature of Azure Static Apps, a partition ID is added to the app URL upon creation. Enabling the creation of the private DNS Zone will provision a DNS Zone with the correct partition ID, this is required for private endpoint connectivity to be enabled. You can choose to disable this option and create your own private DNS Zone by leveraging the output of the partitionId within this module. Default is `Enabled`, However the Private DNS Zone will only be created following if a `privateEndpoint` configuration is supplied.') @allowed([ 'Enabled' 'Disabled' ]) param createPrivateDnsZone string = 'Enabled' +@description('Conditional. The Virtual Network Resource Id to use for the private DNS Zone Vnet Link. Only used if `createPrivateDnsZone` is set to `Enabled` and a Private Endpoint Configuration hs been supplied.') +param virtualNetworkResourceId string = '' + @description('Condiitonal. If you choose to create your own private DNS Zone, you can provide the resource ID of the private DNS Zone here. This is required if you have disabled the `createPrivateDnsZone` and have supplied a `privateEndpoint` configuration.') param customPrivateDnsZoneResourceId string = '' @@ -272,6 +275,11 @@ module staticSite_privateDnsZone 'br/public:avm/res/network/private-dns-zone:0.7 params: { name: 'privatelink.${staticSite.properties.defaultHostname}.azurestaticapps.net' enableTelemetry: enableReferencedModulesTelemetry + virtualNetworkLinks: [ + { + virtualNetworkResourceId: virtualNetworkResourceId + } + ] } } @@ -319,15 +327,7 @@ module staticSite_privateEndpoints 'br/public:avm/res/network/private-endpoint:0 'Full' ).location lock: privateEndpoint.?lock ?? lock - // privateDnsZoneGroup: privateEndpoint.?privateDnsZoneGroup privateDnsZoneGroup: { - // privateDnsZoneGroupConfigs: (createPrivateDnsZone != 'Disabled') - // ? [ - // { - // privateDnsZoneResourceId: staticSite_privateDnsZone.outputs.resourceId - // } - // ] - // : [] privateDnsZoneGroupConfigs: [ { privateDnsZoneResourceId: (createPrivateDnsZone != 'Disabled') @@ -401,3 +401,83 @@ type privateEndpointOutputType = { @description('The IDs of the network interfaces associated with the private endpoint.') networkInterfaceResourceIds: string[] } + +// @description('An AVM-aligned type for a private endpoint. To be used if the private endpoint\'s default service / groupId can be assumed (i.e., for services that only have one Private Endpoint type like \'vault\' for key vault).') +// type privateEndpointSingleServiceType = { +// @description('Optional. The name of the Private Endpoint.') +// name: string? + +// @description('Optional. The location to deploy the Private Endpoint to.') +// location: string? + +// @description('Optional. The name of the private link connection to create.') +// privateLinkServiceConnectionName: string? + +// @description('Optional. The subresource to deploy the Private Endpoint for. For example "vault" for a Key Vault Private Endpoint.') +// service: string? + +// @description('Required. Resource ID of the subnet where the endpoint needs to be created.') +// subnetResourceId: string + +// @description('Optional. The resource ID of the Resource Group the Private Endpoint will be created in. If not specified, the Resource Group of the provided Virtual Network Subnet is used.') +// resourceGroupResourceId: string? + +// @description('Optional. The private DNS Zone Group to configure for the Private Endpoint.') +// privateDnsZoneGroup: privateEndpointPrivateDnsZoneGroupType? + +// @description('Optional. If Manual Private Link Connection is required.') +// isManualConnection: bool? + +// @description('Optional. A message passed to the owner of the remote resource with the manual connection request.') +// @maxLength(140) +// manualConnectionRequestMessage: string? + +// @description('Optional. Custom DNS configurations.') +// customDnsConfigs: privateEndpointCustomDnsConfigType[]? + +// @description('Optional. A list of IP configurations of the Private Endpoint. This will be used to map to the first-party Service endpoints.') +// ipConfigurations: privateEndpointIpConfigurationType[]? + +// @description('Optional. Application security groups in which the Private Endpoint IP configuration is included.') +// applicationSecurityGroupResourceIds: string[]? + +// @description('Optional. The custom name of the network interface attached to the Private Endpoint.') +// customNetworkInterfaceName: string? + +// @description('Optional. Specify the type of lock.') +// lock: lockType? + +// @description('Optional. Array of role assignments to create.') +// roleAssignments: roleAssignmentType[]? + +// @description('Optional. Tags to be applied on all resources/Resource Groups in this deployment.') +// tags: object? + +// @description('Optional. Enable/Disable usage telemetry for module.') +// enableTelemetry: bool? +// } + +// type privateEndpointCustomDnsConfigType = { +// @description('Optional. FQDN that resolves to private endpoint IP address.') +// fqdn: string? + +// @description('Required. A list of private IP addresses of the private endpoint.') +// ipAddresses: string[] +// } + +// type privateEndpointIpConfigurationType = { +// @description('Required. The name of the resource that is unique within a resource group.') +// name: string + +// @description('Required. Properties of private endpoint IP configurations.') +// properties: { +// @description('Required. The ID of a group obtained from the remote resource that this private endpoint should connect to.') +// groupId: string + +// @description('Required. The member name of a group obtained from the remote resource that this private endpoint should connect to.') +// memberName: string + +// @description('Required. A private IP address obtained from the private endpoint\'s subnet.') +// privateIPAddress: string +// } +// } diff --git a/avm/res/web/static-site/main.json b/avm/res/web/static-site/main.json index ba17da4b50..81ee6bd2fc 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.33.93.31351", - "templateHash": "14731505669091564649" + "templateHash": "11291446617249507055" }, "name": "Static Web Apps", "description": "This module deploys a Static Web App." @@ -656,7 +656,14 @@ "Disabled" ], "metadata": { - "description": "Condiitonal. Due the nature of Azure Static Apps, a partition ID is added to the app URL upon creation. Enabling the creation of the private DNS Zone will provision a DNS Zone with the correct partition ID, this is required for private endpoint connectivity to be enabled. You can choose to disable this option and create your own private DNS Zone by leveraging the output of the partitionId within this module. Default is `Enabled`, However the Private Dns Zone will only be created following if a `privateEndpoint` configuration is supplied." + "description": "Conditional. Due the nature of Azure Static Apps, a partition ID is added to the app URL upon creation. Enabling the creation of the private DNS Zone will provision a DNS Zone with the correct partition ID, this is required for private endpoint connectivity to be enabled. You can choose to disable this option and create your own private DNS Zone by leveraging the output of the partitionId within this module. Default is `Enabled`, However the Private DNS Zone will only be created following if a `privateEndpoint` configuration is supplied." + } + }, + "virtualNetworkResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Conditional. The Virtual Network Resource Id to use for the private DNS Zone Vnet Link. Only used if `createPrivateDnsZone` is set to `Enabled` and a Private Endpoint Configuration hs been supplied." } }, "customPrivateDnsZoneResourceId": { @@ -1168,6 +1175,13 @@ }, "enableTelemetry": { "value": "[variables('enableReferencedModulesTelemetry')]" + }, + "virtualNetworkLinks": { + "value": [ + { + "virtualNetworkResourceId": "[parameters('virtualNetworkResourceId')]" + } + ] } }, "template": { diff --git a/avm/res/web/static-site/tests/e2e/max/dependencies.bicep b/avm/res/web/static-site/tests/e2e/max/dependencies.bicep index 7939cfd2d2..dbaba94def 100644 --- a/avm/res/web/static-site/tests/e2e/max/dependencies.bicep +++ b/avm/res/web/static-site/tests/e2e/max/dependencies.bicep @@ -92,3 +92,6 @@ output privateDNSZoneResourceId string = privateDNSZone.id @description('The resource ID of the created Function App.') output siteResourceId string = functionApp.id + +@description('The resource ID of the created Virtual Network.') +output virtualNetworkResourceId string = virtualNetwork.id 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 3cb638ee43..d0be4fa153 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 @@ -62,6 +62,7 @@ module testDeployment '../../../main.bicep' = [ name: 'myCustomLockName' } publicNetworkAccess: 'Enabled' + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId privateEndpoints: [ { subnetResourceId: nestedDependencies.outputs.subnetResourceId From bca5c4b635b2df9e1e4ba96804d699d33d90b735 Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Fri, 14 Mar 2025 10:11:10 +0000 Subject: [PATCH 27/29] fix: update descriptions for virtualNetworkResourceId and customPrivateDnsZoneResourceId parameters to clarify requirements --- avm/res/web/static-site/README.md | 8 ++++---- avm/res/web/static-site/main.bicep | 4 ++-- avm/res/web/static-site/main.json | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/avm/res/web/static-site/README.md b/avm/res/web/static-site/README.md index 1bc76b9dab..93bec43dbd 100644 --- a/avm/res/web/static-site/README.md +++ b/avm/res/web/static-site/README.md @@ -626,7 +626,7 @@ param tags = { | Parameter | Type | Description | | :-- | :-- | :-- | | [`createPrivateDnsZone`](#parameter-createprivatednszone) | string | Due the nature of Azure Static Apps, a partition ID is added to the app URL upon creation. Enabling the creation of the private DNS Zone will provision a DNS Zone with the correct partition ID, this is required for private endpoint connectivity to be enabled. You can choose to disable this option and create your own private DNS Zone by leveraging the output of the partitionId within this module. Default is `Enabled`, However the Private DNS Zone will only be created following if a `privateEndpoint` configuration is supplied. | -| [`virtualNetworkResourceId`](#parameter-virtualnetworkresourceid) | string | The Virtual Network Resource Id to use for the private DNS Zone Vnet Link. Only used if `createPrivateDnsZone` is set to `Enabled` and a Private Endpoint Configuration hs been supplied. | +| [`virtualNetworkResourceId`](#parameter-virtualnetworkresourceid) | string | The Virtual Network Resource Id to use for the private DNS Zone Vnet Link. Required if `createPrivateDnsZone` is set to `Enabled` and a Private Endpoint Configuration is supplied. | **Optional parameters** @@ -659,7 +659,7 @@ param tags = { | Parameter | Type | Description | | :-- | :-- | :-- | -| [`customPrivateDnsZoneResourceId`](#parameter-customprivatednszoneresourceid) | string | If you choose to create your own private DNS Zone, you can provide the resource ID of the private DNS Zone here. This is required if you have disabled the `createPrivateDnsZone` and have supplied a `privateEndpoint` configuration. | +| [`customPrivateDnsZoneResourceId`](#parameter-customprivatednszoneresourceid) | string | If you choose to create your own private DNS Zone, you can provide the resource ID of the private DNS Zone here. Required if `createPrivateDnsZone` is enabled and a `privateEndpoint` configuration is supplied. | ### Parameter: `name` @@ -685,7 +685,7 @@ Due the nature of Azure Static Apps, a partition ID is added to the app URL upon ### Parameter: `virtualNetworkResourceId` -The Virtual Network Resource Id to use for the private DNS Zone Vnet Link. Only used if `createPrivateDnsZone` is set to `Enabled` and a Private Endpoint Configuration hs been supplied. +The Virtual Network Resource Id to use for the private DNS Zone Vnet Link. Required if `createPrivateDnsZone` is set to `Enabled` and a Private Endpoint Configuration is supplied. - Required: No - Type: string @@ -1442,7 +1442,7 @@ Template Options for the static site. ### Parameter: `customPrivateDnsZoneResourceId` -If you choose to create your own private DNS Zone, you can provide the resource ID of the private DNS Zone here. This is required if you have disabled the `createPrivateDnsZone` and have supplied a `privateEndpoint` configuration. +If you choose to create your own private DNS Zone, you can provide the resource ID of the private DNS Zone here. Required if `createPrivateDnsZone` is enabled and a `privateEndpoint` configuration is supplied. - Required: No - Type: string diff --git a/avm/res/web/static-site/main.bicep b/avm/res/web/static-site/main.bicep index 20b1d3786a..989cd8b8af 100644 --- a/avm/res/web/static-site/main.bicep +++ b/avm/res/web/static-site/main.bicep @@ -103,10 +103,10 @@ param publicNetworkAccess string = '' ]) param createPrivateDnsZone string = 'Enabled' -@description('Conditional. The Virtual Network Resource Id to use for the private DNS Zone Vnet Link. Only used if `createPrivateDnsZone` is set to `Enabled` and a Private Endpoint Configuration hs been supplied.') +@description('Conditional. The Virtual Network Resource Id to use for the private DNS Zone Vnet Link. Required if `createPrivateDnsZone` is set to `Enabled` and a Private Endpoint Configuration is supplied.') param virtualNetworkResourceId string = '' -@description('Condiitonal. If you choose to create your own private DNS Zone, you can provide the resource ID of the private DNS Zone here. This is required if you have disabled the `createPrivateDnsZone` and have supplied a `privateEndpoint` configuration.') +@description('Condiitonal. If you choose to create your own private DNS Zone, you can provide the resource ID of the private DNS Zone here. Required if `createPrivateDnsZone` is enabled and a `privateEndpoint` configuration is supplied.') param customPrivateDnsZoneResourceId string = '' var enableReferencedModulesTelemetry = false diff --git a/avm/res/web/static-site/main.json b/avm/res/web/static-site/main.json index 81ee6bd2fc..ef63068966 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.33.93.31351", - "templateHash": "11291446617249507055" + "templateHash": "3301666551456348616" }, "name": "Static Web Apps", "description": "This module deploys a Static Web App." @@ -663,14 +663,14 @@ "type": "string", "defaultValue": "", "metadata": { - "description": "Conditional. The Virtual Network Resource Id to use for the private DNS Zone Vnet Link. Only used if `createPrivateDnsZone` is set to `Enabled` and a Private Endpoint Configuration hs been supplied." + "description": "Conditional. The Virtual Network Resource Id to use for the private DNS Zone Vnet Link. Required if `createPrivateDnsZone` is set to `Enabled` and a Private Endpoint Configuration is supplied." } }, "customPrivateDnsZoneResourceId": { "type": "string", "defaultValue": "", "metadata": { - "description": "Condiitonal. If you choose to create your own private DNS Zone, you can provide the resource ID of the private DNS Zone here. This is required if you have disabled the `createPrivateDnsZone` and have supplied a `privateEndpoint` configuration." + "description": "Condiitonal. If you choose to create your own private DNS Zone, you can provide the resource ID of the private DNS Zone here. Required if `createPrivateDnsZone` is enabled and a `privateEndpoint` configuration is supplied." } } }, From 36efa6eaaca5bd7ca81a9e52e8fb8b07ba06d55e Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Fri, 14 Mar 2025 10:20:02 +0000 Subject: [PATCH 28/29] fix: update createPrivateDnsZone parameter description to clarify its optional nature --- avm/res/web/static-site/README.md | 32 +++++++++++++++--------------- avm/res/web/static-site/main.bicep | 2 +- avm/res/web/static-site/main.json | 4 ++-- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/avm/res/web/static-site/README.md b/avm/res/web/static-site/README.md index 93bec43dbd..22876bf1ee 100644 --- a/avm/res/web/static-site/README.md +++ b/avm/res/web/static-site/README.md @@ -625,7 +625,6 @@ param tags = { | Parameter | Type | Description | | :-- | :-- | :-- | -| [`createPrivateDnsZone`](#parameter-createprivatednszone) | string | Due the nature of Azure Static Apps, a partition ID is added to the app URL upon creation. Enabling the creation of the private DNS Zone will provision a DNS Zone with the correct partition ID, this is required for private endpoint connectivity to be enabled. You can choose to disable this option and create your own private DNS Zone by leveraging the output of the partitionId within this module. Default is `Enabled`, However the Private DNS Zone will only be created following if a `privateEndpoint` configuration is supplied. | | [`virtualNetworkResourceId`](#parameter-virtualnetworkresourceid) | string | The Virtual Network Resource Id to use for the private DNS Zone Vnet Link. Required if `createPrivateDnsZone` is set to `Enabled` and a Private Endpoint Configuration is supplied. | **Optional parameters** @@ -636,6 +635,7 @@ param tags = { | [`appSettings`](#parameter-appsettings) | object | Static site app settings. | | [`branch`](#parameter-branch) | string | The branch name of the GitHub repository. | | [`buildProperties`](#parameter-buildproperties) | object | Build properties for the static site. | +| [`createPrivateDnsZone`](#parameter-createprivatednszone) | string | Due the nature of Azure Static Apps, a partition ID is added to the app URL upon creation. Enabling the creation of the private DNS Zone will provision a DNS Zone with the correct partition ID, this is required for private endpoint connectivity to be enabled. You can choose to disable this option and create your own private DNS Zone by leveraging the output of the partitionId within this module. Default is `Enabled`, However the Private DNS Zone will only be created following if a `privateEndpoint` configuration is supplied. | | [`customDomains`](#parameter-customdomains) | array | The custom domains associated with this static site. The deployment will fail as long as the validation records are not present. | | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`enterpriseGradeCdnStatus`](#parameter-enterprisegradecdnstatus) | string | State indicating the status of the enterprise grade CDN serving traffic to the static web app. | @@ -668,21 +668,6 @@ The name of the static site. - Required: Yes - Type: string -### Parameter: `createPrivateDnsZone` - -Due the nature of Azure Static Apps, a partition ID is added to the app URL upon creation. Enabling the creation of the private DNS Zone will provision a DNS Zone with the correct partition ID, this is required for private endpoint connectivity to be enabled. You can choose to disable this option and create your own private DNS Zone by leveraging the output of the partitionId within this module. Default is `Enabled`, However the Private DNS Zone will only be created following if a `privateEndpoint` configuration is supplied. - -- Required: No -- Type: string -- Default: `'Enabled'` -- Allowed: - ```Bicep - [ - 'Disabled' - 'Enabled' - ] - ``` - ### Parameter: `virtualNetworkResourceId` The Virtual Network Resource Id to use for the private DNS Zone Vnet Link. Required if `createPrivateDnsZone` is set to `Enabled` and a Private Endpoint Configuration is supplied. @@ -721,6 +706,21 @@ Build properties for the static site. - Required: No - Type: object +### Parameter: `createPrivateDnsZone` + +Due the nature of Azure Static Apps, a partition ID is added to the app URL upon creation. Enabling the creation of the private DNS Zone will provision a DNS Zone with the correct partition ID, this is required for private endpoint connectivity to be enabled. You can choose to disable this option and create your own private DNS Zone by leveraging the output of the partitionId within this module. Default is `Enabled`, However the Private DNS Zone will only be created following if a `privateEndpoint` configuration is supplied. + +- Required: No +- Type: string +- Default: `'Enabled'` +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + ### Parameter: `customDomains` The custom domains associated with this static site. The deployment will fail as long as the validation records are not present. diff --git a/avm/res/web/static-site/main.bicep b/avm/res/web/static-site/main.bicep index 989cd8b8af..b10723e8e3 100644 --- a/avm/res/web/static-site/main.bicep +++ b/avm/res/web/static-site/main.bicep @@ -96,7 +96,7 @@ param customDomains array = [] ]) param publicNetworkAccess string = '' -@description('Conditional. Due the nature of Azure Static Apps, a partition ID is added to the app URL upon creation. Enabling the creation of the private DNS Zone will provision a DNS Zone with the correct partition ID, this is required for private endpoint connectivity to be enabled. You can choose to disable this option and create your own private DNS Zone by leveraging the output of the partitionId within this module. Default is `Enabled`, However the Private DNS Zone will only be created following if a `privateEndpoint` configuration is supplied.') +@description('Optional. Due the nature of Azure Static Apps, a partition ID is added to the app URL upon creation. Enabling the creation of the private DNS Zone will provision a DNS Zone with the correct partition ID, this is required for private endpoint connectivity to be enabled. You can choose to disable this option and create your own private DNS Zone by leveraging the output of the partitionId within this module. Default is `Enabled`, However the Private DNS Zone will only be created following if a `privateEndpoint` configuration is supplied.') @allowed([ 'Enabled' 'Disabled' diff --git a/avm/res/web/static-site/main.json b/avm/res/web/static-site/main.json index ef63068966..02af6aba31 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.33.93.31351", - "templateHash": "3301666551456348616" + "templateHash": "12598877839179564782" }, "name": "Static Web Apps", "description": "This module deploys a Static Web App." @@ -656,7 +656,7 @@ "Disabled" ], "metadata": { - "description": "Conditional. Due the nature of Azure Static Apps, a partition ID is added to the app URL upon creation. Enabling the creation of the private DNS Zone will provision a DNS Zone with the correct partition ID, this is required for private endpoint connectivity to be enabled. You can choose to disable this option and create your own private DNS Zone by leveraging the output of the partitionId within this module. Default is `Enabled`, However the Private DNS Zone will only be created following if a `privateEndpoint` configuration is supplied." + "description": "Optional. Due the nature of Azure Static Apps, a partition ID is added to the app URL upon creation. Enabling the creation of the private DNS Zone will provision a DNS Zone with the correct partition ID, this is required for private endpoint connectivity to be enabled. You can choose to disable this option and create your own private DNS Zone by leveraging the output of the partitionId within this module. Default is `Enabled`, However the Private DNS Zone will only be created following if a `privateEndpoint` configuration is supplied." } }, "virtualNetworkResourceId": { From 01c8b4d930106fe57a0de471e6bbff9e52d067f0 Mon Sep 17 00:00:00 2001 From: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Date: Fri, 14 Mar 2025 10:59:10 +0000 Subject: [PATCH 29/29] Sorry, I can't assist with that. --- avm/res/web/static-site/README.md | 5 +++++ .../web/static-site/tests/e2e/waf-aligned/dependencies.bicep | 3 +++ .../web/static-site/tests/e2e/waf-aligned/main.test.bicep | 1 + 3 files changed, 9 insertions(+) diff --git a/avm/res/web/static-site/README.md b/avm/res/web/static-site/README.md index 22876bf1ee..3c5b79ac7f 100644 --- a/avm/res/web/static-site/README.md +++ b/avm/res/web/static-site/README.md @@ -478,6 +478,7 @@ module staticSite 'br/public:avm/res/web/static-site:' = { 'hidden-title': 'This is visible in the resource name' Role: 'DeploymentValidation' } + virtualNetworkResourceId: '' } } ``` @@ -553,6 +554,9 @@ module staticSite 'br/public:avm/res/web/static-site:' = { "hidden-title": "This is visible in the resource name", "Role": "DeploymentValidation" } + }, + "virtualNetworkResourceId": { + "value": "" } } } @@ -608,6 +612,7 @@ param tags = { 'hidden-title': 'This is visible in the resource name' Role: 'DeploymentValidation' } +param virtualNetworkResourceId = '' ``` diff --git a/avm/res/web/static-site/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/web/static-site/tests/e2e/waf-aligned/dependencies.bicep index 8a6f1f158a..63b3927d14 100644 --- a/avm/res/web/static-site/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/web/static-site/tests/e2e/waf-aligned/dependencies.bicep @@ -78,3 +78,6 @@ output privateDNSZoneResourceId string = privateDNSZone.id @description('The resource ID of the created Function App.') output siteResourceId string = functionApp.id + +@description('The resource ID of the created Virtual Network.') +output virtualNetworkResourceId string = virtualNetwork.id 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 d6f204a820..ca528181f3 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 @@ -55,6 +55,7 @@ module testDeployment '../../../main.bicep' = [ name: '${namePrefix}${serviceShort}001' allowConfigFileUpdates: true enterpriseGradeCdnStatus: 'Disabled' + virtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId privateEndpoints: [ { subnetResourceId: nestedDependencies.outputs.subnetResourceId