From c428930d49446d0429b168cb9fa91e29ff827751 Mon Sep 17 00:00:00 2001 From: Clint Grove <30802291+clintgrove@users.noreply.github.com> Date: Tue, 6 Feb 2024 17:03:40 +0000 Subject: [PATCH 1/3] fix: remove orphan out of databricks/workspace (#940) ## Description removing orphan from readme ## Adding a new module - [ ] A proposal has been submitted and approved. - [ ] I have included "Closes #{module_proposal_issue_number}" in the PR description. - [ ] I have run `brm validate` locally to verify the module files. - [ ] I have run deployment tests locally to ensure the module is deployable. ## Updating an existing module - [x] This is a bug fix: - [x] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] I have run `brm validate` locally to verify the module files. - [ ] I have run deployment tests locally to ensure the module is deployable. - [ ] I have read the [Updating an existing module](https://github.com/Azure/bicep-registry-modules/blob/main/CONTRIBUTING.md#updating-an-existing-module) section in the contributing guide and updated the `version.json` file properly: - [ ] The PR contains backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`. - [ ] The PR contains backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] The PR contains breaking changes, and I have bumped the MAJOR version in `version.json`. - [x] I have updated the examples in README with the latest module version number. --- avm/res/databricks/workspace/ORPHANED.md | 4 ---- avm/res/databricks/workspace/README.md | 5 ----- 2 files changed, 9 deletions(-) delete mode 100644 avm/res/databricks/workspace/ORPHANED.md diff --git a/avm/res/databricks/workspace/ORPHANED.md b/avm/res/databricks/workspace/ORPHANED.md deleted file mode 100644 index ef8fa911d2..0000000000 --- a/avm/res/databricks/workspace/ORPHANED.md +++ /dev/null @@ -1,4 +0,0 @@ -⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ - -- Only security and bug fixes are being handled by the AVM core team at present. -- If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! \ No newline at end of file diff --git a/avm/res/databricks/workspace/README.md b/avm/res/databricks/workspace/README.md index 337845699b..00a0d04ccb 100644 --- a/avm/res/databricks/workspace/README.md +++ b/avm/res/databricks/workspace/README.md @@ -1,10 +1,5 @@ # Azure Databricks Workspaces `[Microsoft.Databricks/workspaces]` -> ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ -> -> - Only security and bug fixes are being handled by the AVM core team at present. -> - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! - This module deploys an Azure Databricks Workspace. ## Navigation From 59b028053e1ac80002e0879f026d5b3e990e7636 Mon Sep 17 00:00:00 2001 From: Ahmad Abdalla <28486158+ahmadabdalla@users.noreply.github.com> Date: Wed, 7 Feb 2024 08:13:07 +1100 Subject: [PATCH 2/3] feat: avm/res/insights/private-link-scope (#873) ## Description Closes https://github.com/Azure/Azure-Verified-Modules/issues/511 Closes https://github.com/Azure/ResourceModules/issues/4416 ### Pipeline [![avm.res.insights.private-link-scope](https://github.com/ahmadabdalla/bicep-registry-modules/actions/workflows/avm.res.insights.private-link-scope.yml/badge.svg?branch=users%2Fahmad%2F4413_privateLinkScopes)](https://github.com/ahmadabdalla/bicep-registry-modules/actions/workflows/avm.res.insights.private-link-scope.yml) ### Teams ![image](https://github.com/Azure/bicep-registry-modules/assets/28486158/effb9699-a9e8-46f1-93c8-a13741ccf81e) ![image](https://github.com/Azure/bicep-registry-modules/assets/28486158/4310b327-21bf-4dc2-9122-01acfb7c90c3) If you haven't already, read the full [contribution guide](https://github.com/Azure/bicep-registry-modules/blob/main/CONTRIBUTING.md). The guide may have changed since the last time you read it, so please double-check. Once you are done and ready to submit your PR, edit the PR description and run through the relevant checklist below. Enable GitHub Workflows in your fork to enable auto-generation of assets with our [GitHub Action](/.github/workflows/push-auto-generate.yml). To trigger GitHub Actions after auto-generation, [add a GitHub PAT](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) as a secret in your forked repository called `PAT`. ## Adding a new module - [x] A proposal has been submitted and approved. - [x] I have included "Closes #{module_proposal_issue_number}" in the PR description. - [x] I have run `brm validate` locally to verify the module files. - [x] I have run deployment tests locally to ensure the module is deployable. ## Updating an existing module - [ ] This is a bug fix: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] I have run `brm validate` locally to verify the module files. - [ ] I have run deployment tests locally to ensure the module is deployable. - [ ] I have read the [Updating an existing module](https://github.com/Azure/bicep-registry-modules/blob/main/CONTRIBUTING.md#updating-an-existing-module) section in the contributing guide and updated the `version.json` file properly: - [ ] The PR contains backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`. - [ ] The PR contains backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] The PR contains breaking changes, and I have bumped the MAJOR version in `version.json`. - [ ] I have updated the examples in README with the latest module version number. --------- Co-authored-by: Alexander Sehr Co-authored-by: Erika Gressi <56914614+eriqua@users.noreply.github.com> --- .github/CODEOWNERS | 2 +- .github/ISSUE_TEMPLATE/avm_module_issue.yml | 2 +- .../avm.res.insights.private-link-scope.yml | 85 ++ avm/res/insights/private-link-scope/README.md | 1267 ++++++++++++++++ .../insights/private-link-scope/main.bicep | 292 ++++ avm/res/insights/private-link-scope/main.json | 1312 +++++++++++++++++ .../scoped-resource/README.md | 70 + .../scoped-resource/main.bicep | 35 + .../scoped-resource/main.json | 69 + .../tests/e2e/defaults/main.test.bicep | 46 + .../tests/e2e/max/dependencies.bicep | 71 + .../tests/e2e/max/main.test.bicep | 214 +++ .../tests/e2e/waf-aligned/dependencies.bicep | 60 + .../tests/e2e/waf-aligned/main.test.bicep | 173 +++ .../insights/private-link-scope/version.json | 7 + 15 files changed, 3703 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/avm.res.insights.private-link-scope.yml create mode 100644 avm/res/insights/private-link-scope/README.md create mode 100644 avm/res/insights/private-link-scope/main.bicep create mode 100644 avm/res/insights/private-link-scope/main.json create mode 100644 avm/res/insights/private-link-scope/scoped-resource/README.md create mode 100644 avm/res/insights/private-link-scope/scoped-resource/main.bicep create mode 100644 avm/res/insights/private-link-scope/scoped-resource/main.json create mode 100644 avm/res/insights/private-link-scope/tests/e2e/defaults/main.test.bicep create mode 100644 avm/res/insights/private-link-scope/tests/e2e/max/dependencies.bicep create mode 100644 avm/res/insights/private-link-scope/tests/e2e/max/main.test.bicep create mode 100644 avm/res/insights/private-link-scope/tests/e2e/waf-aligned/dependencies.bicep create mode 100644 avm/res/insights/private-link-scope/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/res/insights/private-link-scope/version.json diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 4e96375bd2..e7a433a7f2 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -61,7 +61,7 @@ /avm/res/insights/data-collection-rule/ @Azure/avm-res-insights-datacollectionrule-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/insights/diagnostic-setting/ @Azure/avm-res-insights-diagnosticsetting-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/insights/metric-alert/ @Azure/avm-res-insights-metricalert-module-owners-bicep @Azure/avm-core-team-technical-bicep -#/avm/res/insights/private-link-scope/ @Azure/avm-res-insights-privatelinkscope-module-owners-bicep @Azure/avm-core-team-technical-bicep +/avm/res/insights/private-link-scope/ @Azure/avm-res-insights-privatelinkscope-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/insights/scheduled-query-rule/ @Azure/avm-res-insights-scheduledqueryrule-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/insights/webtest/ @Azure/avm-res-insights-webtest-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/key-vault/vault/ @Azure/avm-res-keyvault-vault-module-owners-bicep @Azure/avm-core-team-technical-bicep diff --git a/.github/ISSUE_TEMPLATE/avm_module_issue.yml b/.github/ISSUE_TEMPLATE/avm_module_issue.yml index e63cb0bb99..1904159067 100644 --- a/.github/ISSUE_TEMPLATE/avm_module_issue.yml +++ b/.github/ISSUE_TEMPLATE/avm_module_issue.yml @@ -95,7 +95,7 @@ body: - "avm/res/insights/data-collection-rule" - "avm/res/insights/diagnostic-setting" - "avm/res/insights/metric-alert" - # - "avm/res/insights/private-link-scope" + - "avm/res/insights/private-link-scope" - "avm/res/insights/scheduled-query-rule" - "avm/res/insights/webtest" - "avm/res/key-vault/vault" diff --git a/.github/workflows/avm.res.insights.private-link-scope.yml b/.github/workflows/avm.res.insights.private-link-scope.yml new file mode 100644 index 0000000000..7c353ac15c --- /dev/null +++ b/.github/workflows/avm.res.insights.private-link-scope.yml @@ -0,0 +1,85 @@ +name: "avm.res.insights.private-link-scope" + +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.insights.private-link-scope.yml" + - "avm/res/insights/private-link-scope/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/insights/private-link-scope" + workflowPath: ".github/workflows/avm.res.insights.private-link-scope.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-latest + name: "Initialize pipeline" + steps: + - name: "Checkout" + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: "Set input parameters to output variables" + id: get-workflow-param + uses: ./.github/actions/templates/avm-getWorkflowInput + with: + workflowPath: "${{ env.workflowPath}}" + - name: "Get module test file paths" + id: get-module-test-file-paths + uses: ./.github/actions/templates/avm-getModuleTestFiles + with: + modulePath: "${{ env.modulePath }}" + outputs: + workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }} + moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} + psRuleModuleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.psRuleModuleTestFilePaths }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Run" + permissions: + id-token: write # For OIDC + contents: write # For release tags + needs: + - job_initialize_pipeline + uses: ./.github/workflows/avm.template.module.yml + with: + workflowInput: "${{ needs.job_initialize_pipeline.outputs.workflowInput }}" + moduleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.moduleTestFilePaths }}" + psRuleModuleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.psRuleModuleTestFilePaths }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit diff --git a/avm/res/insights/private-link-scope/README.md b/avm/res/insights/private-link-scope/README.md new file mode 100644 index 0000000000..993930664c --- /dev/null +++ b/avm/res/insights/private-link-scope/README.md @@ -0,0 +1,1267 @@ +# Azure Monitor Private Link Scopes `[microsoft.insights/privateLinkScopes]` + +This module deploys an Azure Monitor Private Link Scope. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | +| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | +| `microsoft.insights/privateLinkScopes` | [2021-07-01-preview](https://learn.microsoft.com/en-us/azure/templates/microsoft.insights/2021-07-01-preview/privateLinkScopes) | +| `Microsoft.Insights/privateLinkScopes/scopedResources` | [2021-07-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-07-01-preview/privateLinkScopes/scopedResources) | +| `Microsoft.Network/privateEndpoints` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/privateEndpoints) | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/privateEndpoints/privateDnsZoneGroups) | + +## Usage examples + +The following section provides usage examples for the module, which were used to validate and deploy the module successfully. For a full reference, please review the module's test folder in its repository. + +>**Note**: Each example lists all the required parameters first, followed by the rest - each in alphabetical order. + +>**Note**: To reference the module, please use the following syntax `br/public:avm/res/insights/private-link-scope:`. + +- [Using only defaults](#example-1-using-only-defaults) +- [Using large parameter set](#example-2-using-large-parameter-set) +- [WAF-aligned](#example-3-waf-aligned) + +### Example 1: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. + + +
+ +via Bicep module + +```bicep + name: '${uniqueString(deployment().name, resourceLocation)}-test-iplsmin' + params: { + // Required parameters + name: 'iplsmin001' + // Non-required parameters + location: 'global' + } +} +``` + +
+

+ +

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

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

+ +via Bicep module + +```bicep + name: '${uniqueString(deployment().name, resourceLocation)}-test-iplsmax' + params: { + // Required parameters + name: 'iplsmax001' + // Non-required parameters + accessModeSettings: { + exclusions: [ + { + ingestionAccessMode: 'PrivateOnly' + privateEndpointConnectionName: 'thisisatest' + queryAccessMode: 'PrivateOnly' + } + ] + ingestionAccessMode: 'Open' + queryAccessMode: 'Open' + } + location: 'global' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + privateEndpoints: [ + { + customNetworkInterfaceName: 'nic-pe-' + ipConfigurations: [ + { + name: 'api' + properties: { + groupId: 'azuremonitor' + memberName: 'api' + privateIPAddress: '10.0.0.11' + } + } + { + name: 'globalinai' + properties: { + groupId: 'azuremonitor' + memberName: 'global.in.ai' + privateIPAddress: '10.0.0.12' + } + } + { + name: 'profiler' + properties: { + groupId: 'azuremonitor' + memberName: 'profiler' + privateIPAddress: '10.0.0.13' + } + } + { + name: 'live' + properties: { + groupId: 'azuremonitor' + memberName: 'live' + privateIPAddress: '10.0.0.14' + } + } + { + name: 'diagservicesquery' + properties: { + groupId: 'azuremonitor' + memberName: 'diagservicesquery' + privateIPAddress: '10.0.0.15' + } + } + { + name: 'snapshot' + properties: { + groupId: 'azuremonitor' + memberName: 'snapshot' + privateIPAddress: '10.0.0.16' + } + } + { + name: 'agentsolutionpackstore' + properties: { + groupId: 'azuremonitor' + memberName: 'agentsolutionpackstore' + privateIPAddress: '10.0.0.17' + } + } + { + name: 'dce-global' + properties: { + groupId: 'azuremonitor' + memberName: 'dce-global' + privateIPAddress: '10.0.0.18' + } + } + { + name: '' + properties: { + groupId: 'azuremonitor' + memberName: '' + privateIPAddress: '10.0.0.19' + } + } + { + name: '' + properties: { + groupId: 'azuremonitor' + memberName: '' + privateIPAddress: '10.0.0.20' + } + } + { + name: '' + properties: { + groupId: 'azuremonitor' + memberName: '' + privateIPAddress: '10.0.0.21' + } + } + ] + name: 'pe-' + privateDnsZoneResourceIds: [ + '' + ] + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + subnetResourceId: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + ] + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + scopedResources: [ + { + linkedResourceId: '' + name: 'scoped1' + } + ] + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "iplsmax001" + }, + // Non-required parameters + "accessModeSettings": { + "value": { + "exclusions": [ + { + "ingestionAccessMode": "PrivateOnly", + "privateEndpointConnectionName": "thisisatest", + "queryAccessMode": "PrivateOnly" + } + ], + "ingestionAccessMode": "Open", + "queryAccessMode": "Open" + } + }, + "location": { + "value": "global" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "privateEndpoints": { + "value": [ + { + "customNetworkInterfaceName": "nic-pe-", + "ipConfigurations": [ + { + "name": "api", + "properties": { + "groupId": "azuremonitor", + "memberName": "api", + "privateIPAddress": "10.0.0.11" + } + }, + { + "name": "globalinai", + "properties": { + "groupId": "azuremonitor", + "memberName": "global.in.ai", + "privateIPAddress": "10.0.0.12" + } + }, + { + "name": "profiler", + "properties": { + "groupId": "azuremonitor", + "memberName": "profiler", + "privateIPAddress": "10.0.0.13" + } + }, + { + "name": "live", + "properties": { + "groupId": "azuremonitor", + "memberName": "live", + "privateIPAddress": "10.0.0.14" + } + }, + { + "name": "diagservicesquery", + "properties": { + "groupId": "azuremonitor", + "memberName": "diagservicesquery", + "privateIPAddress": "10.0.0.15" + } + }, + { + "name": "snapshot", + "properties": { + "groupId": "azuremonitor", + "memberName": "snapshot", + "privateIPAddress": "10.0.0.16" + } + }, + { + "name": "agentsolutionpackstore", + "properties": { + "groupId": "azuremonitor", + "memberName": "agentsolutionpackstore", + "privateIPAddress": "10.0.0.17" + } + }, + { + "name": "dce-global", + "properties": { + "groupId": "azuremonitor", + "memberName": "dce-global", + "privateIPAddress": "10.0.0.18" + } + }, + { + "name": "", + "properties": { + "groupId": "azuremonitor", + "memberName": "", + "privateIPAddress": "10.0.0.19" + } + }, + { + "name": "", + "properties": { + "groupId": "azuremonitor", + "memberName": "", + "privateIPAddress": "10.0.0.20" + } + }, + { + "name": "", + "properties": { + "groupId": "azuremonitor", + "memberName": "", + "privateIPAddress": "10.0.0.21" + } + } + ], + "name": "pe-", + "privateDnsZoneResourceIds": [ + "" + ], + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ], + "subnetResourceId": "", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + ] + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "scopedResources": { + "value": [ + { + "linkedResourceId": "", + "name": "scoped1" + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep + name: '${uniqueString(deployment().name, resourceLocation)}-test-iplswaf' + params: { + // Required parameters + name: 'iplswaf001' + // Non-required parameters + location: 'global' + privateEndpoints: [ + { + customNetworkInterfaceName: 'nic-pe-' + ipConfigurations: [ + { + name: 'api' + properties: { + groupId: 'azuremonitor' + memberName: 'api' + privateIPAddress: '10.0.0.11' + } + } + { + name: 'globalinai' + properties: { + groupId: 'azuremonitor' + memberName: 'global.in.ai' + privateIPAddress: '10.0.0.12' + } + } + { + name: 'profiler' + properties: { + groupId: 'azuremonitor' + memberName: 'profiler' + privateIPAddress: '10.0.0.13' + } + } + { + name: 'live' + properties: { + groupId: 'azuremonitor' + memberName: 'live' + privateIPAddress: '10.0.0.14' + } + } + { + name: 'diagservicesquery' + properties: { + groupId: 'azuremonitor' + memberName: 'diagservicesquery' + privateIPAddress: '10.0.0.15' + } + } + { + name: 'snapshot' + properties: { + groupId: 'azuremonitor' + memberName: 'snapshot' + privateIPAddress: '10.0.0.16' + } + } + { + name: 'agentsolutionpackstore' + properties: { + groupId: 'azuremonitor' + memberName: 'agentsolutionpackstore' + privateIPAddress: '10.0.0.17' + } + } + { + name: 'dce-global' + properties: { + groupId: 'azuremonitor' + memberName: 'dce-global' + privateIPAddress: '10.0.0.18' + } + } + { + name: '' + properties: { + groupId: 'azuremonitor' + memberName: '' + privateIPAddress: '10.0.0.19' + } + } + { + name: '' + properties: { + groupId: 'azuremonitor' + memberName: '' + privateIPAddress: '10.0.0.20' + } + } + { + name: '' + properties: { + groupId: 'azuremonitor' + memberName: '' + privateIPAddress: '10.0.0.21' + } + } + ] + name: 'pe-' + privateDnsZoneResourceIds: [ + '' + ] + subnetResourceId: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + ] + scopedResources: [ + { + linkedResourceId: '' + name: 'scoped1' + } + ] + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "iplswaf001" + }, + // Non-required parameters + "location": { + "value": "global" + }, + "privateEndpoints": { + "value": [ + { + "customNetworkInterfaceName": "nic-pe-", + "ipConfigurations": [ + { + "name": "api", + "properties": { + "groupId": "azuremonitor", + "memberName": "api", + "privateIPAddress": "10.0.0.11" + } + }, + { + "name": "globalinai", + "properties": { + "groupId": "azuremonitor", + "memberName": "global.in.ai", + "privateIPAddress": "10.0.0.12" + } + }, + { + "name": "profiler", + "properties": { + "groupId": "azuremonitor", + "memberName": "profiler", + "privateIPAddress": "10.0.0.13" + } + }, + { + "name": "live", + "properties": { + "groupId": "azuremonitor", + "memberName": "live", + "privateIPAddress": "10.0.0.14" + } + }, + { + "name": "diagservicesquery", + "properties": { + "groupId": "azuremonitor", + "memberName": "diagservicesquery", + "privateIPAddress": "10.0.0.15" + } + }, + { + "name": "snapshot", + "properties": { + "groupId": "azuremonitor", + "memberName": "snapshot", + "privateIPAddress": "10.0.0.16" + } + }, + { + "name": "agentsolutionpackstore", + "properties": { + "groupId": "azuremonitor", + "memberName": "agentsolutionpackstore", + "privateIPAddress": "10.0.0.17" + } + }, + { + "name": "dce-global", + "properties": { + "groupId": "azuremonitor", + "memberName": "dce-global", + "privateIPAddress": "10.0.0.18" + } + }, + { + "name": "", + "properties": { + "groupId": "azuremonitor", + "memberName": "", + "privateIPAddress": "10.0.0.19" + } + }, + { + "name": "", + "properties": { + "groupId": "azuremonitor", + "memberName": "", + "privateIPAddress": "10.0.0.20" + } + }, + { + "name": "", + "properties": { + "groupId": "azuremonitor", + "memberName": "", + "privateIPAddress": "10.0.0.21" + } + } + ], + "name": "pe-", + "privateDnsZoneResourceIds": [ + "" + ], + "subnetResourceId": "", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + ] + }, + "scopedResources": { + "value": [ + { + "linkedResourceId": "", + "name": "scoped1" + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

+ + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the private link scope. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`accessModeSettings`](#parameter-accessmodesettings) | object | Specifies the access mode of ingestion or queries through associated private endpoints in scope. For security reasons, it is recommended to use PrivateOnly whenever possible to avoid data exfiltration. + + * Private Only - This mode allows the connected virtual network to reach only Private Link resources. It is the most secure mode and is set as the default when the `privateEndpoints` parameter is configured. + * Open - Allows the connected virtual network to reach both Private Link resources and the resources not in the AMPLS resource. Data exfiltration cannot be prevented in this mode. | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`location`](#parameter-location) | string | The location of the private link scope. Should be global. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`privateEndpoints`](#parameter-privateendpoints) | array | Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`scopedResources`](#parameter-scopedresources) | array | Configuration details for Azure Monitor Resources. | +| [`tags`](#parameter-tags) | object | Resource tags. | + +### Parameter: `name` + +Name of the private link scope. + +- Required: Yes +- Type: string + +### Parameter: `accessModeSettings` + +Specifies the access mode of ingestion or queries through associated private endpoints in scope. For security reasons, it is recommended to use PrivateOnly whenever possible to avoid data exfiltration. + + * Private Only - This mode allows the connected virtual network to reach only Private Link resources. It is the most secure mode and is set as the default when the `privateEndpoints` parameter is configured. + * Open - Allows the connected virtual network to reach both Private Link resources and the resources not in the AMPLS resource. Data exfiltration cannot be prevented in this mode. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`exclusions`](#parameter-accessmodesettingsexclusions) | array | List of exclusions that override the default access mode settings for specific private endpoint connections. Exclusions for the current created Private endpoints can only be applied post initial provisioning. | +| [`ingestionAccessMode`](#parameter-accessmodesettingsingestionaccessmode) | string | Specifies the default access mode of ingestion through associated private endpoints in scope. Default is "Open" if no private endpoints are configured and will be set to "PrivateOnly" if private endpoints are configured. Override default behaviour by explicitly providing a value. | +| [`queryAccessMode`](#parameter-accessmodesettingsqueryaccessmode) | string | Specifies the default access mode of queries through associated private endpoints in scope. Default is "Open" if no private endpoints are configured and will be set to "PrivateOnly" if private endpoints are configured. Override default behaviour by explicitly providing a value. | + +### Parameter: `accessModeSettings.exclusions` + +List of exclusions that override the default access mode settings for specific private endpoint connections. Exclusions for the current created Private endpoints can only be applied post initial provisioning. + +- Required: No +- Type: array + +### Parameter: `accessModeSettings.ingestionAccessMode` + +Specifies the default access mode of ingestion through associated private endpoints in scope. Default is "Open" if no private endpoints are configured and will be set to "PrivateOnly" if private endpoints are configured. Override default behaviour by explicitly providing a value. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Open' + 'PrivateOnly' + ] + ``` + +### Parameter: `accessModeSettings.queryAccessMode` + +Specifies the default access mode of queries through associated private endpoints in scope. Default is "Open" if no private endpoints are configured and will be set to "PrivateOnly" if private endpoints are configured. Override default behaviour by explicitly providing a value. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Open' + 'PrivateOnly' + ] + ``` + +### Parameter: `enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `location` + +The location of the private link scope. Should be global. + +- Required: No +- Type: string +- Default: `'global'` + +### Parameter: `lock` + +The lock settings of the service. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`kind`](#parameter-lockkind) | string | Specify the type of lock. | +| [`name`](#parameter-lockname) | string | Specify the name of lock. | + +### Parameter: `lock.kind` + +Specify the type of lock. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'CanNotDelete' + 'None' + 'ReadOnly' + ] + ``` + +### Parameter: `lock.name` + +Specify the name of lock. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints` + +Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`subnetResourceId`](#parameter-privateendpointssubnetresourceid) | string | Resource ID of the subnet where the endpoint needs to be created. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`applicationSecurityGroupResourceIds`](#parameter-privateendpointsapplicationsecuritygroupresourceids) | array | Application security groups in which the private endpoint IP configuration is included. | +| [`customDnsConfigs`](#parameter-privateendpointscustomdnsconfigs) | array | Custom DNS configurations. | +| [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the private endpoint. | +| [`enableTelemetry`](#parameter-privateendpointsenabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. | +| [`location`](#parameter-privateendpointslocation) | string | The location to deploy the private endpoint to. | +| [`lock`](#parameter-privateendpointslock) | object | Specify the type of lock. | +| [`manualPrivateLinkServiceConnections`](#parameter-privateendpointsmanualprivatelinkserviceconnections) | array | Manual PrivateLink Service Connections. | +| [`name`](#parameter-privateendpointsname) | string | The name of the private endpoint. | +| [`privateDnsZoneGroupName`](#parameter-privateendpointsprivatednszonegroupname) | string | The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided. | +| [`privateDnsZoneResourceIds`](#parameter-privateendpointsprivatednszoneresourceids) | array | The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones. | +| [`roleAssignments`](#parameter-privateendpointsroleassignments) | array | Array of role assignments to create. | +| [`service`](#parameter-privateendpointsservice) | string | The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". | +| [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/resource groups in this deployment. | + +### Parameter: `privateEndpoints.subnetResourceId` + +Resource ID of the subnet where the endpoint needs to be created. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.applicationSecurityGroupResourceIds` + +Application security groups in which the private endpoint IP configuration is included. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.customDnsConfigs` + +Custom DNS configurations. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.customNetworkInterfaceName` + +The custom name of the network interface attached to the private endpoint. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool + +### Parameter: `privateEndpoints.ipConfigurations` + +A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.location` + +The location to deploy the private endpoint to. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.lock` + +Specify the type of lock. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`kind`](#parameter-privateendpointslockkind) | string | Specify the type of lock. | +| [`name`](#parameter-privateendpointslockname) | string | Specify the name of lock. | + +### Parameter: `privateEndpoints.lock.kind` + +Specify the type of lock. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'CanNotDelete' + 'None' + 'ReadOnly' + ] + ``` + +### Parameter: `privateEndpoints.lock.name` + +Specify the name of lock. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.manualPrivateLinkServiceConnections` + +Manual PrivateLink Service Connections. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.name` + +The name of the private endpoint. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.privateDnsZoneGroupName` + +The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.privateDnsZoneResourceIds` + +The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`principalId`](#parameter-privateendpointsroleassignmentsprincipalid) | string | The principal ID of the principal (user/group/identity) to assign the role to. | +| [`roleDefinitionIdOrName`](#parameter-privateendpointsroleassignmentsroledefinitionidorname) | string | The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`condition`](#parameter-privateendpointsroleassignmentscondition) | string | The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container". | +| [`conditionVersion`](#parameter-privateendpointsroleassignmentsconditionversion) | string | Version of the condition. | +| [`delegatedManagedIdentityResourceId`](#parameter-privateendpointsroleassignmentsdelegatedmanagedidentityresourceid) | string | The Resource Id of the delegated managed identity resource. | +| [`description`](#parameter-privateendpointsroleassignmentsdescription) | string | The description of the role assignment. | +| [`principalType`](#parameter-privateendpointsroleassignmentsprincipaltype) | string | The principal type of the assigned principal ID. | + +### Parameter: `privateEndpoints.roleAssignments.principalId` + +The principal ID of the principal (user/group/identity) to assign the role to. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.roleAssignments.roleDefinitionIdOrName` + +The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.roleAssignments.condition` + +The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container". + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.roleAssignments.conditionVersion` + +Version of the condition. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + '2.0' + ] + ``` + +### Parameter: `privateEndpoints.roleAssignments.delegatedManagedIdentityResourceId` + +The Resource Id of the delegated managed identity resource. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.roleAssignments.description` + +The description of the role assignment. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.roleAssignments.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `privateEndpoints.service` + +The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.tags` + +Tags to be applied on all resources/resource groups in this deployment. + +- Required: No +- Type: object + +### Parameter: `roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`principalId`](#parameter-roleassignmentsprincipalid) | string | The principal ID of the principal (user/group/identity) to assign the role to. | +| [`roleDefinitionIdOrName`](#parameter-roleassignmentsroledefinitionidorname) | string | The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`condition`](#parameter-roleassignmentscondition) | string | The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container". | +| [`conditionVersion`](#parameter-roleassignmentsconditionversion) | string | Version of the condition. | +| [`delegatedManagedIdentityResourceId`](#parameter-roleassignmentsdelegatedmanagedidentityresourceid) | string | The Resource Id of the delegated managed identity resource. | +| [`description`](#parameter-roleassignmentsdescription) | string | The description of the role assignment. | +| [`principalType`](#parameter-roleassignmentsprincipaltype) | string | The principal type of the assigned principal ID. | + +### Parameter: `roleAssignments.principalId` + +The principal ID of the principal (user/group/identity) to assign the role to. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.roleDefinitionIdOrName` + +The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.condition` + +The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container". + +- Required: No +- Type: string + +### Parameter: `roleAssignments.conditionVersion` + +Version of the condition. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + '2.0' + ] + ``` + +### Parameter: `roleAssignments.delegatedManagedIdentityResourceId` + +The Resource Id of the delegated managed identity resource. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.description` + +The description of the role assignment. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `scopedResources` + +Configuration details for Azure Monitor Resources. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`linkedResourceId`](#parameter-scopedresourceslinkedresourceid) | string | The resource ID of the scoped Azure monitor resource. | +| [`name`](#parameter-scopedresourcesname) | string | Name of the private link scoped resource. | + +### Parameter: `scopedResources.linkedResourceId` + +The resource ID of the scoped Azure monitor resource. + +- Required: Yes +- Type: string + +### Parameter: `scopedResources.name` + +Name of the private link scoped resource. + +- Required: Yes +- Type: string + +### Parameter: `tags` + +Resource tags. + +- Required: No +- Type: object + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the private link scope. | +| `resourceGroupName` | string | The resource group the private link scope was deployed into. | +| `resourceId` | string | The resource ID of the private link scope. | + +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other CARML modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/res/network/private-endpoint:0.3.1` | Remote reference | + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/insights/private-link-scope/main.bicep b/avm/res/insights/private-link-scope/main.bicep new file mode 100644 index 0000000000..cd58ee6903 --- /dev/null +++ b/avm/res/insights/private-link-scope/main.bicep @@ -0,0 +1,292 @@ +metadata name = 'Azure Monitor Private Link Scopes' +metadata description = 'This module deploys an Azure Monitor Private Link Scope.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. Name of the private link scope.') +@minLength(1) +param name string + +@description('''Optional. Specifies the access mode of ingestion or queries through associated private endpoints in scope. For security reasons, it is recommended to use PrivateOnly whenever possible to avoid data exfiltration. + + * Private Only - This mode allows the connected virtual network to reach only Private Link resources. It is the most secure mode and is set as the default when the `privateEndpoints` parameter is configured. + * Open - Allows the connected virtual network to reach both Private Link resources and the resources not in the AMPLS resource. Data exfiltration cannot be prevented in this mode.''') +param accessModeSettings accessModeType + +@description('Optional. The location of the private link scope. Should be global.') +param location string = 'global' + +@description('Optional. The lock settings of the service.') +param lock lockType + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +@description('Optional. Configuration details for Azure Monitor Resources.') +param scopedResources scopedResourceType + +@description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') +param privateEndpoints privateEndpointType + +@description('Optional. Resource tags.') +param tags object? + +@sys.description('Optional. Enable/Disable usage telemetry for module.') +param enableTelemetry bool = true + +var builtInRoleNames = { + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 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') + 'Tag Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4a9ae827-6dc8-4573-8ac7-8239d42aa03f') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.insights-privatelinkscope.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } + } + } + } +} + +resource privateLinkScope 'microsoft.insights/privateLinkScopes@2021-07-01-preview' = { + name: name + location: location + tags: tags + properties: { + accessModeSettings: !empty(privateEndpoints) ? { + ingestionAccessMode: accessModeSettings.?ingestionAccessMode ?? 'PrivateOnly' + queryAccessMode: accessModeSettings.?queryAccessMode ?? 'PrivateOnly' + exclusions: accessModeSettings.?exclusions ?? [] + } : accessModeSettings ?? { + ingestionAccessMode: accessModeSettings.?ingestionAccessMode ?? 'Open' + queryAccessMode: accessModeSettings.?queryAccessMode ?? 'Open' + exclusions: accessModeSettings.?exclusions ?? [] + } + } +} + +module privateLinkScope_scopedResource 'scoped-resource/main.bicep' = [for (scopedResource, index) in (scopedResources ?? []): { + name: '${uniqueString(deployment().name, location)}-PrivateLinkScope-ScopedResource-${index}' + params: { + name: scopedResource.name + privateLinkScopeName: privateLinkScope.name + linkedResourceId: scopedResource.linkedResourceId + } +}] + +resource privateLinkScope_lock 'Microsoft.Authorization/locks@2020-05-01' = if (!empty(lock ?? {}) && lock.?kind != 'None') { + name: lock.?name ?? 'lock-${name}' + properties: { + level: lock.?kind ?? '' + notes: lock.?kind == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot delete or modify the resource or child resources.' + } + scope: privateLinkScope +} + +module privateLinkScope_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.3.1' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-PrivateLinkScope-PrivateEndpoint-${index}' + params: { + privateLinkServiceConnections: [ + { + name: name + properties: { + privateLinkServiceId: privateLinkScope.id + groupIds: [ + privateEndpoint.?service ?? 'azuremonitor' + ] + } + } + ] + name: privateEndpoint.?name ?? 'pep-${last(split(privateLinkScope.id, '/'))}-${privateEndpoint.?service ?? 'azuremonitor'}-${index}' + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: enableTelemetry + location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } +}] + +resource privateLinkScope_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(privateLinkScope.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + principalId: roleAssignment.principalId + description: roleAssignment.?description + principalType: roleAssignment.?principalType + condition: roleAssignment.?condition + conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null // Must only be set if condtion is set + delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId + } + scope: privateLinkScope +}] + +@description('The name of the private link scope.') +output name string = privateLinkScope.name + +@description('The resource ID of the private link scope.') +output resourceId string = privateLinkScope.id + +@description('The resource group the private link scope was deployed into.') +output resourceGroupName string = resourceGroup().name + +@description('The location the resource was deployed into.') +output location string = privateLinkScope.location + +// =============== // +// Definitions // +// =============== // + +type lockType = { + @description('Optional. Specify the name of lock.') + name: string? + + @description('Optional. Specify the type of lock.') + kind: ('CanNotDelete' | 'ReadOnly' | 'None')? +}? + +type roleAssignmentType = { + @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') + roleDefinitionIdOrName: string + + @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') + principalId: string + + @description('Optional. The principal type of the assigned principal ID.') + principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? + + @description('Optional. The description of the role assignment.') + description: string? + + @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') + condition: string? + + @description('Optional. Version of the condition.') + conditionVersion: '2.0'? + + @description('Optional. The Resource Id of the delegated managed identity resource.') + delegatedManagedIdentityResourceId: string? +}[]? + +type privateEndpointType = { + @description('Optional. The name of the private endpoint.') + name: string? + + @description('Optional. The location to deploy the private endpoint to.') + location: string? + + @description('Optional. The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob".') + service: string? + + @description('Required. Resource ID of the subnet where the endpoint needs to be created.') + subnetResourceId: string + + @description('Optional. The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided.') + privateDnsZoneGroupName: string? + + @description('Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones.') + privateDnsZoneResourceIds: string[]? + + @description('Optional. Custom DNS configurations.') + customDnsConfigs: { + @description('Required. Fqdn that resolves to private endpoint ip address.') + fqdn: string? + + @description('Required. A list of private ip addresses of the private endpoint.') + ipAddresses: string[] + }[]? + + @description('Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints.') + ipConfigurations: { + @description('Required. The name of the resource that is unique within a resource group.') + name: string + + @description('Required. Properties of private endpoint IP configurations.') + properties: { + @description('Required. The ID of a group obtained from the remote resource that this private endpoint should connect to.') + groupId: string + + @description('Required. The member name of a group obtained from the remote resource that this private endpoint should connect to.') + memberName: string + + @description('Required. A private ip address obtained from the private endpoint\'s subnet.') + privateIPAddress: string + } + }[]? + + @description('Optional. Application security groups in which the private endpoint IP configuration is included.') + applicationSecurityGroupResourceIds: string[]? + + @description('Optional. The custom name of the network interface attached to the private endpoint.') + customNetworkInterfaceName: string? + + @description('Optional. Specify the type of lock.') + lock: lockType + + @description('Optional. Array of role assignments to create.') + roleAssignments: roleAssignmentType + + @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') + tags: object? + + @description('Optional. Manual PrivateLink Service Connections.') + manualPrivateLinkServiceConnections: array? + + @description('Optional. Enable/Disable usage telemetry for module.') + enableTelemetry: bool? +}[]? + +type scopedResourceType = { + @description('Required. Name of the private link scoped resource.') + name: string + + @description('Required. The resource ID of the scoped Azure monitor resource.') + linkedResourceId: string +}[]? + +type accessModeType = { + @description('Optional. List of exclusions that override the default access mode settings for specific private endpoint connections. Exclusions for the current created Private endpoints can only be applied post initial provisioning.') + exclusions: { + @description('Required. The private endpoint connection name associated to the private endpoint on which we want to apply the specific access mode settings.') + privateEndpointConnectionName: string + + @description('Required. Specifies the access mode of ingestion through the specified private endpoint connection in the exclusion.') + ingestionAccessMode: 'Open' | 'PrivateOnly' + + @description('Required. Specifies the access mode of queries through the specified private endpoint connection in the exclusion.') + queryAccessMode: 'Open' | 'PrivateOnly' + }[]? + + @description('Optional. Specifies the default access mode of ingestion through associated private endpoints in scope. Default is "Open" if no private endpoints are configured and will be set to "PrivateOnly" if private endpoints are configured. Override default behaviour by explicitly providing a value.') + ingestionAccessMode: 'Open' | 'PrivateOnly'? + + @description('Optional. Specifies the default access mode of queries through associated private endpoints in scope. Default is "Open" if no private endpoints are configured and will be set to "PrivateOnly" if private endpoints are configured. Override default behaviour by explicitly providing a value.') + queryAccessMode: 'Open' | 'PrivateOnly'? +}? diff --git a/avm/res/insights/private-link-scope/main.json b/avm/res/insights/private-link-scope/main.json new file mode 100644 index 0000000000..4b6d2aa1e8 --- /dev/null +++ b/avm/res/insights/private-link-scope/main.json @@ -0,0 +1,1312 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "13333472574597727627" + }, + "name": "Azure Monitor Private Link Scopes", + "description": "This module deploys an Azure Monitor Private Link Scope.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "privateEndpointType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private endpoint." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The location to deploy the private endpoint to." + } + }, + "service": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The service (sub-) type to deploy the private endpoint for. For example \"vault\" or \"blob\"." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "privateDnsZoneGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided." + } + }, + "privateDnsZoneResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Required. Fqdn that resolves to private endpoint ip address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private ip addresses of the private endpoint." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "ipConfigurations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private ip address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. Specify the type of lock." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "manualPrivateLinkServiceConnections": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Manual PrivateLink Service Connections." + } + }, + "enableTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + } + }, + "nullable": true + }, + "scopedResourceType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the private link scoped resource." + } + }, + "linkedResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the scoped Azure monitor resource." + } + } + } + }, + "nullable": true + }, + "accessModeType": { + "type": "object", + "properties": { + "exclusions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "privateEndpointConnectionName": { + "type": "string", + "metadata": { + "description": "Required. The private endpoint connection name associated to the private endpoint on which we want to apply the specific access mode settings." + } + }, + "ingestionAccessMode": { + "type": "string", + "allowedValues": [ + "Open", + "PrivateOnly" + ], + "metadata": { + "description": "Required. Specifies the access mode of ingestion through the specified private endpoint connection in the exclusion." + } + }, + "queryAccessMode": { + "type": "string", + "allowedValues": [ + "Open", + "PrivateOnly" + ], + "metadata": { + "description": "Required. Specifies the access mode of queries through the specified private endpoint connection in the exclusion." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. List of exclusions that override the default access mode settings for specific private endpoint connections. Exclusions for the current created Private endpoints can only be applied post initial provisioning." + } + }, + "ingestionAccessMode": { + "type": "string", + "allowedValues": [ + "Open", + "PrivateOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specifies the default access mode of ingestion through associated private endpoints in scope. Default is \"Open\" if no private endpoints are configured and will be set to \"PrivateOnly\" if private endpoints are configured. Override default behaviour by explicitly providing a value." + } + }, + "queryAccessMode": { + "type": "string", + "allowedValues": [ + "Open", + "PrivateOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specifies the default access mode of queries through associated private endpoints in scope. Default is \"Open\" if no private endpoints are configured and will be set to \"PrivateOnly\" if private endpoints are configured. Override default behaviour by explicitly providing a value." + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "Required. Name of the private link scope." + } + }, + "accessModeSettings": { + "$ref": "#/definitions/accessModeType", + "metadata": { + "description": "Optional. Specifies the access mode of ingestion or queries through associated private endpoints in scope. For security reasons, it is recommended to use PrivateOnly whenever possible to avoid data exfiltration.\n\n * Private Only - This mode allows the connected virtual network to reach only Private Link resources. It is the most secure mode and is set as the default when the `privateEndpoints` parameter is configured.\n * Open - Allows the connected virtual network to reach both Private Link resources and the resources not in the AMPLS resource. Data exfiltration cannot be prevented in this mode." + } + }, + "location": { + "type": "string", + "defaultValue": "global", + "metadata": { + "description": "Optional. The location of the private link scope. Should be global." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "scopedResources": { + "$ref": "#/definitions/scopedResourceType", + "metadata": { + "description": "Optional. Configuration details for Azure Monitor Resources." + } + }, + "privateEndpoints": { + "$ref": "#/definitions/privateEndpointType", + "metadata": { + "description": "Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "Tag Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4a9ae827-6dc8-4573-8ac7-8239d42aa03f')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.insights-privatelinkscope.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "privateLinkScope": { + "type": "microsoft.insights/privateLinkScopes", + "apiVersion": "2021-07-01-preview", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "accessModeSettings": "[if(not(empty(parameters('privateEndpoints'))), createObject('ingestionAccessMode', coalesce(tryGet(parameters('accessModeSettings'), 'ingestionAccessMode'), 'PrivateOnly'), 'queryAccessMode', coalesce(tryGet(parameters('accessModeSettings'), 'queryAccessMode'), 'PrivateOnly'), 'exclusions', coalesce(tryGet(parameters('accessModeSettings'), 'exclusions'), createArray())), coalesce(parameters('accessModeSettings'), createObject('ingestionAccessMode', coalesce(tryGet(parameters('accessModeSettings'), 'ingestionAccessMode'), 'Open'), 'queryAccessMode', coalesce(tryGet(parameters('accessModeSettings'), 'queryAccessMode'), 'Open'), 'exclusions', coalesce(tryGet(parameters('accessModeSettings'), 'exclusions'), createArray()))))]" + } + }, + "privateLinkScope_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.insights/privateLinkScopes/{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": [ + "privateLinkScope" + ] + }, + "privateLinkScope_roleAssignments": { + "copy": { + "name": "privateLinkScope_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('microsoft.insights/privateLinkScopes/{0}', parameters('name'))]", + "name": "[guid(resourceId('microsoft.insights/privateLinkScopes', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", + "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "privateLinkScope" + ] + }, + "privateLinkScope_scopedResource": { + "copy": { + "name": "privateLinkScope_scopedResource", + "count": "[length(coalesce(parameters('scopedResources'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateLinkScope-ScopedResource-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(parameters('scopedResources'), createArray())[copyIndex()].name]" + }, + "privateLinkScopeName": { + "value": "[parameters('name')]" + }, + "linkedResourceId": { + "value": "[coalesce(parameters('scopedResources'), createArray())[copyIndex()].linkedResourceId]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "7629126178221322122" + }, + "name": "Private Link Scope Scoped Resources", + "description": "This module deploys a Private Link Scope Scoped Resource.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "Required. Name of the private link scoped resource." + } + }, + "privateLinkScopeName": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "Conditional. The name of the parent private link scope. Required if the template is used in a standalone deployment." + } + }, + "linkedResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the scoped Azure monitor resource." + } + } + }, + "resources": [ + { + "type": "Microsoft.Insights/privateLinkScopes/scopedResources", + "apiVersion": "2021-07-01-preview", + "name": "[format('{0}/{1}', parameters('privateLinkScopeName'), parameters('name'))]", + "properties": { + "linkedResourceId": "[parameters('linkedResourceId')]" + } + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group where the resource has been deployed." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed scopedResource." + }, + "value": "[resourceId('Microsoft.Insights/privateLinkScopes/scopedResources', parameters('privateLinkScopeName'), parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The full name of the deployed Scoped Resource." + }, + "value": "[parameters('name')]" + } + } + } + }, + "dependsOn": [ + "privateLinkScope" + ] + }, + "privateLinkScope_privateEndpoints": { + "copy": { + "name": "privateLinkScope_privateEndpoints", + "count": "[length(coalesce(parameters('privateEndpoints'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateLinkScope-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateLinkServiceConnections": { + "value": [ + { + "name": "[parameters('name')]", + "properties": { + "privateLinkServiceId": "[resourceId('microsoft.insights/privateLinkScopes', parameters('name'))]", + "groupIds": [ + "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'azuremonitor')]" + ] + } + } + ] + }, + "name": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('microsoft.insights/privateLinkScopes', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'azuremonitor'), copyIndex()))]" + }, + "subnetResourceId": { + "value": "[coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId]" + }, + "enableTelemetry": { + "value": "[parameters('enableTelemetry')]" + }, + "location": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'location'), reference(split(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location)]" + }, + "lock": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'lock'), parameters('lock'))]" + }, + "privateDnsZoneGroupName": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneGroupName')]" + }, + "privateDnsZoneResourceIds": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneResourceIds')]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'roleAssignments')]" + }, + "tags": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" + }, + "manualPrivateLinkServiceConnections": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections')]" + }, + "customDnsConfigs": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customDnsConfigs')]" + }, + "ipConfigurations": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'ipConfigurations')]" + }, + "applicationSecurityGroupResourceIds": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'applicationSecurityGroupResourceIds')]" + }, + "customNetworkInterfaceName": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customNetworkInterfaceName')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "2821141217598568122" + }, + "name": "Private Endpoints", + "description": "This module deploys a Private Endpoint.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"" + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "ipConfigurationsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private ip address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true + }, + "manualPrivateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "privateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "customDnsConfigType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "metadata": { + "description": "Required. Fqdn that resolves to private endpoint ip address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private ip addresses of the private endpoint." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the private endpoint resource to create." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "ipConfigurations": { + "$ref": "#/definitions/ipConfigurationsType", + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "privateDnsZoneGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided." + } + }, + "privateDnsZoneResourceIds": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "customDnsConfigs": { + "$ref": "#/definitions/customDnsConfigType", + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "manualPrivateLinkServiceConnections": { + "$ref": "#/definitions/manualPrivateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource. Used when the network admin does not have access to approve connections to the remote resource." + } + }, + "privateLinkServiceConnections": { + "$ref": "#/definitions/privateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "DNS Resolver Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'eeaeda52-9324-47f6-8069-5d5bade478b2')]", + "Domain Services Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '361898ef-9ed1-48c2-849c-a832951106bb')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.3.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "privateEndpoint": { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-04-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "copy": [ + { + "name": "applicationSecurityGroups", + "count": "[length(coalesce(parameters('applicationSecurityGroupResourceIds'), createArray()))]", + "input": { + "id": "[coalesce(parameters('applicationSecurityGroupResourceIds'), createArray())[copyIndex('applicationSecurityGroups')]]" + } + } + ], + "customDnsConfigs": "[coalesce(parameters('customDnsConfigs'), createArray())]", + "customNetworkInterfaceName": "[coalesce(parameters('customNetworkInterfaceName'), '')]", + "ipConfigurations": "[coalesce(parameters('ipConfigurations'), createArray())]", + "manualPrivateLinkServiceConnections": "[coalesce(parameters('manualPrivateLinkServiceConnections'), createArray())]", + "privateLinkServiceConnections": "[coalesce(parameters('privateLinkServiceConnections'), createArray())]", + "subnet": { + "id": "[parameters('subnetResourceId')]" + } + } + }, + "privateEndpoint_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + }, + "privateEndpoint_roleAssignments": { + "copy": { + "name": "privateEndpoint_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Network/privateEndpoints', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", + "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + }, + "privateEndpoint_privateDnsZoneGroup": { + "condition": "[not(empty(parameters('privateDnsZoneResourceIds')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateEndpoint-PrivateDnsZoneGroup', uniqueString(deployment().name))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(parameters('privateDnsZoneGroupName'), 'default')]" + }, + "privateDNSResourceIds": { + "value": "[coalesce(parameters('privateDnsZoneResourceIds'), createArray())]" + }, + "privateEndpointName": { + "value": "[parameters('name')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "18168683629401652671" + }, + "name": "Private Endpoint Private DNS Zone Groups", + "description": "This module deploys a Private Endpoint Private DNS Zone Group.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "privateEndpointName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent private endpoint. Required if the template is used in a standalone deployment." + } + }, + "privateDNSResourceIds": { + "type": "array", + "minLength": 1, + "maxLength": 5, + "metadata": { + "description": "Required. Array of private DNS zone resource IDs. A DNS zone group can support up to 5 DNS zones." + } + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the private DNS zone group." + } + } + }, + "variables": { + "copy": [ + { + "name": "privateDnsZoneConfigs", + "count": "[length(parameters('privateDNSResourceIds'))]", + "input": { + "name": "[last(split(parameters('privateDNSResourceIds')[copyIndex('privateDnsZoneConfigs')], '/'))]", + "properties": { + "privateDnsZoneId": "[parameters('privateDNSResourceIds')[copyIndex('privateDnsZoneConfigs')]]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2023-04-01", + "name": "[format('{0}/{1}', parameters('privateEndpointName'), parameters('name'))]", + "properties": { + "privateDnsZoneConfigs": "[variables('privateDnsZoneConfigs')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint DNS zone group." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint DNS zone group." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints/privateDnsZoneGroups', parameters('privateEndpointName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint DNS zone group was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateEndpoint" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints', parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('privateEndpoint', '2023-04-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "privateLinkScope" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the private link scope." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private link scope." + }, + "value": "[resourceId('microsoft.insights/privateLinkScopes', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private link scope was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('privateLinkScope', '2021-07-01-preview', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/insights/private-link-scope/scoped-resource/README.md b/avm/res/insights/private-link-scope/scoped-resource/README.md new file mode 100644 index 0000000000..28a9842521 --- /dev/null +++ b/avm/res/insights/private-link-scope/scoped-resource/README.md @@ -0,0 +1,70 @@ +# Private Link Scope Scoped Resources `[Microsoft.Insights/privateLinkScopes/scopedResources]` + +This module deploys a Private Link Scope Scoped Resource. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Insights/privateLinkScopes/scopedResources` | [2021-07-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-07-01-preview/privateLinkScopes/scopedResources) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`linkedResourceId`](#parameter-linkedresourceid) | string | The resource ID of the scoped Azure monitor resource. | +| [`name`](#parameter-name) | string | Name of the private link scoped resource. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`privateLinkScopeName`](#parameter-privatelinkscopename) | string | The name of the parent private link scope. Required if the template is used in a standalone deployment. | + +### Parameter: `linkedResourceId` + +The resource ID of the scoped Azure monitor resource. + +- Required: Yes +- Type: string + +### Parameter: `name` + +Name of the private link scoped resource. + +- Required: Yes +- Type: string + +### Parameter: `privateLinkScopeName` + +The name of the parent private link scope. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The full name of the deployed Scoped Resource. | +| `resourceGroupName` | string | The name of the resource group where the resource has been deployed. | +| `resourceId` | string | The resource ID of the deployed scopedResource. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/insights/private-link-scope/scoped-resource/main.bicep b/avm/res/insights/private-link-scope/scoped-resource/main.bicep new file mode 100644 index 0000000000..94241f25fc --- /dev/null +++ b/avm/res/insights/private-link-scope/scoped-resource/main.bicep @@ -0,0 +1,35 @@ +metadata name = 'Private Link Scope Scoped Resources' +metadata description = 'This module deploys a Private Link Scope Scoped Resource.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. Name of the private link scoped resource.') +@minLength(1) +param name string + +@description('Conditional. The name of the parent private link scope. Required if the template is used in a standalone deployment.') +@minLength(1) +param privateLinkScopeName string + +@description('Required. The resource ID of the scoped Azure monitor resource.') +param linkedResourceId string + +resource privateLinkScope 'Microsoft.Insights/privateLinkScopes@2021-07-01-preview' existing = { + name: privateLinkScopeName +} + +resource scopedResource 'Microsoft.Insights/privateLinkScopes/scopedResources@2021-07-01-preview' = { + name: name + parent: privateLinkScope + properties: { + linkedResourceId: linkedResourceId + } +} + +@description('The name of the resource group where the resource has been deployed.') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the deployed scopedResource.') +output resourceId string = scopedResource.id + +@description('The full name of the deployed Scoped Resource.') +output name string = scopedResource.name diff --git a/avm/res/insights/private-link-scope/scoped-resource/main.json b/avm/res/insights/private-link-scope/scoped-resource/main.json new file mode 100644 index 0000000000..75aa135f34 --- /dev/null +++ b/avm/res/insights/private-link-scope/scoped-resource/main.json @@ -0,0 +1,69 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "7629126178221322122" + }, + "name": "Private Link Scope Scoped Resources", + "description": "This module deploys a Private Link Scope Scoped Resource.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "Required. Name of the private link scoped resource." + } + }, + "privateLinkScopeName": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "Conditional. The name of the parent private link scope. Required if the template is used in a standalone deployment." + } + }, + "linkedResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the scoped Azure monitor resource." + } + } + }, + "resources": [ + { + "type": "Microsoft.Insights/privateLinkScopes/scopedResources", + "apiVersion": "2021-07-01-preview", + "name": "[format('{0}/{1}', parameters('privateLinkScopeName'), parameters('name'))]", + "properties": { + "linkedResourceId": "[parameters('linkedResourceId')]" + } + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group where the resource has been deployed." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed scopedResource." + }, + "value": "[resourceId('Microsoft.Insights/privateLinkScopes/scopedResources', parameters('privateLinkScopeName'), parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The full name of the deployed Scoped Resource." + }, + "value": "[parameters('name')]" + } + } +} \ No newline at end of file diff --git a/avm/res/insights/private-link-scope/tests/e2e/defaults/main.test.bicep b/avm/res/insights/private-link-scope/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..7b221cf51c --- /dev/null +++ b/avm/res/insights/private-link-scope/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,46 @@ +targetScope = 'subscription' + +metadata name = 'Using only defaults' +metadata description = 'This instance deploys the module with the minimum set of required parameters.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-insights.privatelinkscopes-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param resourceLocation string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'iplsmin' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: 'global' + } +}] diff --git a/avm/res/insights/private-link-scope/tests/e2e/max/dependencies.bicep b/avm/res/insights/private-link-scope/tests/e2e/max/dependencies.bicep new file mode 100644 index 0000000000..e09c9b5a0c --- /dev/null +++ b/avm/res/insights/private-link-scope/tests/e2e/max/dependencies.bicep @@ -0,0 +1,71 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +@description('Required. The name of the Log Analytics Workspace to create.') +param logAnalyticsWorkspaceName string + +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + } + } + ] + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { + name: 'privatelink.monitor.azure.com' + location: 'global' + + resource virtualNetworkLinks 'virtualNetworkLinks@2020-06-01' = { + name: '${virtualNetwork.name}-vnetlink' + location: 'global' + properties: { + virtualNetwork: { + id: virtualNetwork.id + } + registrationEnabled: false + } + } +} + +resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-12-01-preview' = { + name: logAnalyticsWorkspaceName + location: location +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId + +@description('The resource ID of the created Private DNS Zone.') +output privateDNSZoneResourceId string = privateDNSZone.id + +@description('The resource ID of the created Log Analytics Workspace.') +output logAnalyticsWorkspaceResourceId string = logAnalyticsWorkspace.id diff --git a/avm/res/insights/private-link-scope/tests/e2e/max/main.test.bicep b/avm/res/insights/private-link-scope/tests/e2e/max/main.test.bicep new file mode 100644 index 0000000000..1d3b534580 --- /dev/null +++ b/avm/res/insights/private-link-scope/tests/e2e/max/main.test.bicep @@ -0,0 +1,214 @@ +targetScope = 'subscription' + +metadata name = 'Using large parameter set' +metadata description = 'This instance deploys the module with most of its features enabled.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-insights.privatelinkscopes-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param resourceLocation string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'iplsmax' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + logAnalyticsWorkspaceName: 'dep-${namePrefix}-la-${serviceShort}' + location: resourceLocation + } +} + +// ============== // +// Test Execution // +// ============== // + +var locationUpdated = toLower(replace(resourceLocation, ' ', '')) + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: 'global' + accessModeSettings: { + exclusions: [ + { + ingestionAccessMode: 'PrivateOnly' + queryAccessMode: 'PrivateOnly' + privateEndpointConnectionName: 'thisisatest' + } + ] + ingestionAccessMode: 'Open' + queryAccessMode: 'Open' + } + scopedResources: [ + { + name: 'scoped1' + linkedResourceId: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + privateEndpoints: [ + { + name: 'pe-${namePrefix}' + customNetworkInterfaceName: 'nic-pe-${namePrefix}' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + ipConfigurations: [ + { + name: 'api' + properties: { + groupId: 'azuremonitor' + memberName: 'api' + privateIPAddress: '10.0.0.11' + } + } + { + name: 'globalinai' + properties: { + groupId: 'azuremonitor' + memberName: 'global.in.ai' + privateIPAddress: '10.0.0.12' + } + } + { + name: 'profiler' + properties: { + groupId: 'azuremonitor' + memberName: 'profiler' + privateIPAddress: '10.0.0.13' + } + } + { + name: 'live' + properties: { + groupId: 'azuremonitor' + memberName: 'live' + privateIPAddress: '10.0.0.14' + } + } + { + name: 'diagservicesquery' + properties: { + groupId: 'azuremonitor' + memberName: 'diagservicesquery' + privateIPAddress: '10.0.0.15' + } + } + { + name: 'snapshot' + properties: { + groupId: 'azuremonitor' + memberName: 'snapshot' + privateIPAddress: '10.0.0.16' + } + } + { + name: 'agentsolutionpackstore' + properties: { + groupId: 'azuremonitor' + memberName: 'agentsolutionpackstore' + privateIPAddress: '10.0.0.17' + } + } + { + name: 'dce-global' + properties: { + groupId: 'azuremonitor' + memberName: 'dce-global' + privateIPAddress: '10.0.0.18' + } + } + { + name: 'oms-${locationUpdated}' + properties: { + groupId: 'azuremonitor' + memberName: 'oms-${locationUpdated}' + privateIPAddress: '10.0.0.19' + } + } + { + name: 'ods-${locationUpdated}' + properties: { + groupId: 'azuremonitor' + memberName: 'ods-${locationUpdated}' + privateIPAddress: '10.0.0.20' + } + } + { + name: 'agent-${locationUpdated}' + properties: { + groupId: 'azuremonitor' + memberName: 'agent-${locationUpdated}' + privateIPAddress: '10.0.0.21' + } + } + ] + } + ] + roleAssignments: [ + { + roleDefinitionIdOrName: 'Owner' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + } +}] diff --git a/avm/res/insights/private-link-scope/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/insights/private-link-scope/tests/e2e/waf-aligned/dependencies.bicep new file mode 100644 index 0000000000..83e5706e42 --- /dev/null +++ b/avm/res/insights/private-link-scope/tests/e2e/waf-aligned/dependencies.bicep @@ -0,0 +1,60 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Log Analytics Workspace to create.') +param logAnalyticsWorkspaceName string + +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + } + } + ] + } +} + +resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { + name: 'privatelink.monitor.azure.com' + location: 'global' + + resource virtualNetworkLinks 'virtualNetworkLinks@2020-06-01' = { + name: '${virtualNetwork.name}-vnetlink' + location: 'global' + properties: { + virtualNetwork: { + id: virtualNetwork.id + } + registrationEnabled: false + } + } +} + +resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-12-01-preview' = { + name: logAnalyticsWorkspaceName + location: location +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The resource ID of the created Private DNS Zone.') +output privateDNSZoneResourceId string = privateDNSZone.id + +@description('The resource ID of the created Log Analytics Workspace.') +output logAnalyticsWorkspaceResourceId string = logAnalyticsWorkspace.id diff --git a/avm/res/insights/private-link-scope/tests/e2e/waf-aligned/main.test.bicep b/avm/res/insights/private-link-scope/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..f298c29766 --- /dev/null +++ b/avm/res/insights/private-link-scope/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,173 @@ +targetScope = 'subscription' + +metadata name = 'WAF-aligned' +metadata description = 'This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-insights.privatelinkscopes-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param resourceLocation string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'iplswaf' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + logAnalyticsWorkspaceName: 'dep-${namePrefix}-la-${serviceShort}' + location: resourceLocation + } +} + +// ============== // +// Test Execution // +// ============== // +var locationUpdated = toLower(replace(resourceLocation, ' ', '')) + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: 'global' + scopedResources: [ + { + name: 'scoped1' + linkedResourceId: nestedDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + privateEndpoints: [ + { + name: 'pe-${namePrefix}' + customNetworkInterfaceName: 'nic-pe-${namePrefix}' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + ipConfigurations: [ + { + name: 'api' + properties: { + groupId: 'azuremonitor' + memberName: 'api' + privateIPAddress: '10.0.0.11' + } + } + { + name: 'globalinai' + properties: { + groupId: 'azuremonitor' + memberName: 'global.in.ai' + privateIPAddress: '10.0.0.12' + } + } + { + name: 'profiler' + properties: { + groupId: 'azuremonitor' + memberName: 'profiler' + privateIPAddress: '10.0.0.13' + } + } + { + name: 'live' + properties: { + groupId: 'azuremonitor' + memberName: 'live' + privateIPAddress: '10.0.0.14' + } + } + { + name: 'diagservicesquery' + properties: { + groupId: 'azuremonitor' + memberName: 'diagservicesquery' + privateIPAddress: '10.0.0.15' + } + } + { + name: 'snapshot' + properties: { + groupId: 'azuremonitor' + memberName: 'snapshot' + privateIPAddress: '10.0.0.16' + } + } + { + name: 'agentsolutionpackstore' + properties: { + groupId: 'azuremonitor' + memberName: 'agentsolutionpackstore' + privateIPAddress: '10.0.0.17' + } + } + { + name: 'dce-global' + properties: { + groupId: 'azuremonitor' + memberName: 'dce-global' + privateIPAddress: '10.0.0.18' + } + } + { + name: 'oms-${locationUpdated}' + properties: { + groupId: 'azuremonitor' + memberName: 'oms-${locationUpdated}' + privateIPAddress: '10.0.0.19' + } + } + { + name: 'ods-${locationUpdated}' + properties: { + groupId: 'azuremonitor' + memberName: 'ods-${locationUpdated}' + privateIPAddress: '10.0.0.20' + } + } + { + name: 'agent-${locationUpdated}' + properties: { + groupId: 'azuremonitor' + memberName: 'agent-${locationUpdated}' + privateIPAddress: '10.0.0.21' + } + } + ] + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/insights/private-link-scope/version.json b/avm/res/insights/private-link-scope/version.json new file mode 100644 index 0000000000..83083db694 --- /dev/null +++ b/avm/res/insights/private-link-scope/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.1", + "pathFilters": [ + "./main.json" + ] +} \ No newline at end of file From 059c27dfde1402836960cbbd6d18ec486e247033 Mon Sep 17 00:00:00 2001 From: Alexander Sehr Date: Wed, 7 Feb 2024 08:57:17 +0100 Subject: [PATCH 3/3] fix: Fixed issue with multi-line parameter descriptions (#943) ## Description Fixed issue with multi-line parameter descriptions | Pipeline | | - | | [![avm.res.web.site](https://github.com/AlexanderSehr/bicep-registry-modules/actions/workflows/avm.res.web.site.yml/badge.svg?branch=users%2Falsehr%2F907_readMeFixMultiline&event=workflow_dispatch)](https://github.com/AlexanderSehr/bicep-registry-modules/actions/workflows/avm.res.web.site.yml) | | [![avm.res.compute.gallery](https://github.com/AlexanderSehr/bicep-registry-modules/actions/workflows/avm.res.compute.gallery.yml/badge.svg?branch=users%2Falsehr%2F907_readMeFixMultiline&event=workflow_dispatch)](https://github.com/AlexanderSehr/bicep-registry-modules/actions/workflows/avm.res.compute.gallery.yml) | --------- Co-authored-by: Erika Gressi <56914614+eriqua@users.noreply.github.com> --- avm/res/compute/gallery/image/README.md | 20 ++++--------------- avm/res/web/site/README.md | 12 ++--------- .../sharedScripts/Set-ModuleReadMe.ps1 | 6 +++--- 3 files changed, 9 insertions(+), 29 deletions(-) diff --git a/avm/res/compute/gallery/image/README.md b/avm/res/compute/gallery/image/README.md index 0c99e3a326..c2c50e2644 100644 --- a/avm/res/compute/gallery/image/README.md +++ b/avm/res/compute/gallery/image/README.md @@ -43,14 +43,8 @@ This module deploys an Azure Compute Gallery Image Definition. | [`endOfLife`](#parameter-endoflife) | string | The end of life date of the gallery Image Definition. This property can be used for decommissioning purposes. This property is updatable. Allowed format: 2020-01-10T23:00:00.000Z. | | [`eula`](#parameter-eula) | string | The Eula agreement for the gallery Image Definition. Has to be a valid URL. | | [`excludedDiskTypes`](#parameter-excludeddisktypes) | array | List of the excluded disk types (e.g., Standard_LRS). | -| [`hyperVGeneration`](#parameter-hypervgeneration) | string | The hypervisor generation of the Virtual Machine. -- If this value is not specified, then it is determined by the securityType parameter. -- If the securityType parameter is specified, then the value of hyperVGeneration will be V2, else V1. - | -| [`isAcceleratedNetworkSupported`](#parameter-isacceleratednetworksupported) | bool | Specify if the image supports accelerated networking. -Accelerated networking enables single root I/O virtualization (SR-IOV) to a VM, greatly improving its networking performance. -This high-performance path bypasses the host from the data path, which reduces latency, jitter, and CPU utilization for the most demanding network workloads on supported VM types. - | +| [`hyperVGeneration`](#parameter-hypervgeneration) | string | The hypervisor generation of the Virtual Machine.

  • If this value is not specified, then it is determined by the securityType parameter.
  • If the securityType parameter is specified, then the value of hyperVGeneration will be V2, else V1.

    | +| [`isAcceleratedNetworkSupported`](#parameter-isacceleratednetworksupported) | bool | Specify if the image supports accelerated networking.

    Accelerated networking enables single root I/O virtualization (SR-IOV) to a VM, greatly improving its networking performance.

    This high-performance path bypasses the host from the data path, which reduces latency, jitter, and CPU utilization for the most demanding network workloads on supported VM types.

    | | [`isHibernateSupported`](#parameter-ishibernatesupported) | bool | Specifiy if the image supports hibernation. | | [`location`](#parameter-location) | string | Location for all resources. | | [`maxRecommendedMemory`](#parameter-maxrecommendedmemory) | int | The maximum amount of RAM in GB recommended for this image. | @@ -148,10 +142,7 @@ List of the excluded disk types (e.g., Standard_LRS). ### Parameter: `hyperVGeneration` -The hypervisor generation of the Virtual Machine. -- If this value is not specified, then it is determined by the securityType parameter. -- If the securityType parameter is specified, then the value of hyperVGeneration will be V2, else V1. - +The hypervisor generation of the Virtual Machine.

  • If this value is not specified, then it is determined by the securityType parameter.
  • If the securityType parameter is specified, then the value of hyperVGeneration will be V2, else V1.

    - Required: No - Type: string @@ -165,10 +156,7 @@ The hypervisor generation of the Virtual Machine. ### Parameter: `isAcceleratedNetworkSupported` -Specify if the image supports accelerated networking. -Accelerated networking enables single root I/O virtualization (SR-IOV) to a VM, greatly improving its networking performance. -This high-performance path bypasses the host from the data path, which reduces latency, jitter, and CPU utilization for the most demanding network workloads on supported VM types. - +Specify if the image supports accelerated networking.

    Accelerated networking enables single root I/O virtualization (SR-IOV) to a VM, greatly improving its networking performance.

    This high-performance path bypasses the host from the data path, which reduces latency, jitter, and CPU utilization for the most demanding network workloads on supported VM types.

    - Required: No - Type: bool diff --git a/avm/res/web/site/README.md b/avm/res/web/site/README.md index b348f7f45b..d8bc8743a8 100644 --- a/avm/res/web/site/README.md +++ b/avm/res/web/site/README.md @@ -1121,11 +1121,7 @@ module site 'br/public:avm/res/web/site:' = { | [`clientAffinityEnabled`](#parameter-clientaffinityenabled) | bool | If client affinity is enabled. | | [`clientCertEnabled`](#parameter-clientcertenabled) | bool | To enable client certificate authentication (TLS mutual authentication). | | [`clientCertExclusionPaths`](#parameter-clientcertexclusionpaths) | string | Client certificate authentication comma-separated exclusion paths. | -| [`clientCertMode`](#parameter-clientcertmode) | string | This composes with ClientCertEnabled setting. -- ClientCertEnabled=false means ClientCert is ignored. -- ClientCertEnabled=true and ClientCertMode=Required means ClientCert is required. -- ClientCertEnabled=true and ClientCertMode=Optional means ClientCert is optional or accepted. - | +| [`clientCertMode`](#parameter-clientcertmode) | string | This composes with ClientCertEnabled setting.

  • ClientCertEnabled=false means ClientCert is ignored.
  • ClientCertEnabled=true and ClientCertMode=Required means ClientCert is required.
  • ClientCertEnabled=true and ClientCertMode=Optional means ClientCert is optional or accepted.

    | | [`cloningInfo`](#parameter-cloninginfo) | object | If specified during app creation, the app is cloned from a source app. | | [`containerSize`](#parameter-containersize) | int | Size of the function container. | | [`customDomainVerificationId`](#parameter-customdomainverificationid) | string | Unique identifier that verifies the custom domains assigned to the app. Customer will add this ID to a txt record for verification. | @@ -1248,11 +1244,7 @@ Client certificate authentication comma-separated exclusion paths. ### Parameter: `clientCertMode` -This composes with ClientCertEnabled setting. -- ClientCertEnabled=false means ClientCert is ignored. -- ClientCertEnabled=true and ClientCertMode=Required means ClientCert is required. -- ClientCertEnabled=true and ClientCertMode=Optional means ClientCert is optional or accepted. - +This composes with ClientCertEnabled setting.

  • ClientCertEnabled=false means ClientCert is ignored.
  • ClientCertEnabled=true and ClientCertMode=Required means ClientCert is required.
  • ClientCertEnabled=true and ClientCertMode=Optional means ClientCert is optional or accepted.

    - Required: No - Type: string diff --git a/avm/utilities/pipelines/sharedScripts/Set-ModuleReadMe.ps1 b/avm/utilities/pipelines/sharedScripts/Set-ModuleReadMe.ps1 index a97548796c..a787ba219a 100644 --- a/avm/utilities/pipelines/sharedScripts/Set-ModuleReadMe.ps1 +++ b/avm/utilities/pipelines/sharedScripts/Set-ModuleReadMe.ps1 @@ -306,14 +306,14 @@ function Set-DefinitionSection { } $isRequired = (Get-IsParameterRequired -TemplateFileContent $TemplateFileContent -Parameter $parameter) ? 'Yes' : 'No' - $description = $parameter.ContainsKey('metadata') ? $parameter['metadata']['description'] : $null + $description = $parameter.ContainsKey('metadata') ? $parameter['metadata']['description'].substring("$category. ".Length).Replace("`n- ", '

  • ').Replace("`r`n", '

    ').Replace("`n", '

    ') : $null ##################### # Table content # ##################### # build table for definition properties - $tableSectionContent += ('| [`{0}`]({1}) | {2} | {3} |' -f $parameter.name, $paramIdentifierLink, $type, $description.substring("$category. ".Length)) + $tableSectionContent += ('| [`{0}`]({1}) | {2} | {3} |' -f $parameter.name, $paramIdentifierLink, $type, $description) #################### # List content # @@ -394,7 +394,7 @@ function Set-DefinitionSection { $listSectionContent += @( $paramHeader, ($parameter.ContainsKey('metadata') ? '' : $null), - ($parameter.ContainsKey('metadata') ? $parameter['metadata']['description'].substring("$category. ".Length) : $null), + $description ($parameter.ContainsKey('metadata') ? '' : $null), ('- Required: {0}' -f $isRequired), ('- Type: {0}' -f $type),